Skip to content

Commit

Permalink
Show alert before sending file that exceeds nginx limit
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-white committed Jan 16, 2021
1 parent cad1dd1 commit fbfb621
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/locales/en.json5
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@
"success": "Success!",
"yes": "Yes"
},
"mixin": {
"request": {
"alert": {
"fileSize": "The file “{name}” that you are trying to upload is larger than the 100 MB limit."
}
}
},
"presenter": {
"Form": {
// This is shown for a Form with a blank version name.
Expand Down
37 changes: 23 additions & 14 deletions src/mixins/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ property:
directly mutate this property after defining it.
*/

import i18n from '../i18n';
import { configForPossibleBackendRequest, isProblem, logAxiosError, requestAlertMessage } from '../util/request';

/*
Expand All @@ -42,19 +43,19 @@ of validateStatus). It also accepts the following options:
not a rejected, promise. Use fulfillProblem to identify such responses.
fulfillProblem is passed the Backend Problem. (Any error response that is
not a Problem is automatically considered unsuccessful.) fulfillProblem
should return `true` if the response should be considered successful and
`false` if not.
- problemToAlert. If the request results in an error, request() shows an
alert. By default, the alert message is the same as that of the Backend
should return `true` if the response is considered successful and `false` if
not.
- problemToAlert. If the request results in an error response, request() shows
an alert. By default, the alert message is the same as that of the Backend
Problem. However, there are two ways to show a different message:
1. If a function is specified for problemToAlert, request() passes the
Problem to the function, which has the option to return a different
message. If the function returns `null` or `undefined`, the Problem's
message is used.
2. If (and only if) problemToAlert has not been specified, request() will
check whether the component has specified an i18n message for the Problem
code. For example:
2. If problemToAlert has not been specified, request() will check whether
the component has specified an i18n message for the Problem code. For
example:
<i18n lang="json5">
{
Expand All @@ -69,14 +70,14 @@ of validateStatus). It also accepts the following options:
Return Value
------------
request() returns a promise. The promise will be rejected if the request results
in an error or if the user navigates away from the route that sent the request.
Otherwise the promise should be fulfilled.
request() returns a promise. The promise will be rejected if the request is
invalid or results in an error response or if the user navigates away from the
route that sent the request. Otherwise the promise should be fulfilled.
If you call then() on the promise, note that the request will no longer be in
progress when the then() callback is run (awaitingResponse will equal `false`).
If you call catch() on the promise, your logic should not assume that the
request resulted in an error. Before the then() or catch() callback is run, Vue
If you call then() on the promise, note that the request will not be in progress
when the then() callback is run (awaitingResponse will equal `false`). If you
call catch() on the promise, your logic should not assume that the request
resulted in an error response. Before the then() or catch() callback is run, Vue
will react to the change in awaitingResponse from `true` to `false`, running
watchers and updating the DOM.
*/
Expand All @@ -91,6 +92,14 @@ function request({
if (axiosConfig.validateStatus != null)
throw new Error('validateStatus is not supported. Use fulfillProblem instead.');

const { data } = axiosConfig;
// This limit is set in the nginx config.
if (data != null && data instanceof File && data.size > 100000000) {
// The alert message also mentions the 100 MB limit.
this.$alert().danger(i18n.t('mixin.request.alert.fileSize', data));
return Promise.reject(new Error('file size exceeds limit'));
}

if (this.awaitingResponse != null) this.awaitingResponse = true;

const { session } = this.$store.state.request.data;
Expand Down
41 changes: 41 additions & 0 deletions test/mixins/request.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import TestUtilRequest from '../util/components/request.vue';

import { mockHttp } from '../util/http';
import { mount } from '../util/lifecycle';

describe('mixins/request', () => {
describe('file size exceeds limit', () => {
const largeFile = (name) => {
const file = new File([''], name);
// At least in Headless Chrome, `file` does not have its own `size`
// property, but rather uses the Blob.prototype.size getter.
Object.prototype.hasOwnProperty.call(file, 'size').should.be.false();
Object.defineProperty(file, 'size', { value: 100000001 });
return file;
};

it('does not send a request', () =>
mockHttp()
.mount(TestUtilRequest)
.testNoRequest(component => {
component.vm.post('/v1/projects/1/forms', largeFile('form.xml'));
}));

it('shows a danger alert', () => {
const component = mount(TestUtilRequest);
component.vm.post('/v1/projects/1/forms', largeFile('form.xml'));
component.should.alert('danger', (message) => {
message.should.containEql('form.xml');
});
});

it('returns a rejected promise', () => {
const component = mount(TestUtilRequest);
const result = component.vm.post(
'/v1/projects/1/forms',
largeFile('form.xml')
);
return result.should.be.rejected();
});
});
});
17 changes: 17 additions & 0 deletions test/util/components/request.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<div></div>
</template>

<script>
import request from '../../../src/mixins/request';
export default {
name: 'TestUtilRequest',
mixins: [request()],
data() {
return {
awaitingResponse: false
};
}
};
</script>
9 changes: 9 additions & 0 deletions transifex/strings_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,15 @@
"string": "Yes"
}
},
"mixin": {
"request": {
"alert": {
"fileSize": {
"string": "The file “{name}” that you are trying to upload is larger than the 100 MB limit."
}
}
}
},
"presenter": {
"Form": {
"blankVersion": {
Expand Down

0 comments on commit fbfb621

Please sign in to comment.