Bad Request ZnEntityTooLarge

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
bpi
Reply | Threaded
Open this post in threaded view
|

Bad Request ZnEntityTooLarge

bpi
I have a Seaside application which includes a file upload feature.

renderContentOn: html

html fileUpload
        callback: [ :file | self receiveFile: file ].
        html submitButton: 'Upload‘ ]


In receiveFile: I just save the uploaded file on the file system.

When I upload a file larger than 16 MB an error page is shown with the error message:
Bad Request ZnEntityTooLarge

I found that by using ZnConstants>>maximumEntitySize: I can increase this limit. However, I want to catch this in the image and show an error message to the user.

I tried wrapping receiveFile: and renderContentOn: with an on:do: exception handler for ZnEntityTooLarge. However, neither works. It seems that the error happens before renderContentOn: is even called. I searched the mailing lists but did not come up with an answer.

How can I achieve this in Seaside? Any help would be much appreciated.

Cheers,
Bernhard
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Bad Request ZnEntityTooLarge

Sven Van Caekenberghe-2
Hi Bernard,

Your analysis is correct.

Most Seaside adaptors, including ZnZincServerAdaptor, are implemented so that the incoming (Zn) request is read from the wire, then converted to Seaside WA* objects, processed, the result converted from WA* objects to an outgoing (Zn) response and put on the wire.

Zn has some built-in resource protection measures, including a limit on how large entities (bodies) can be. The error of crossing such a limit is raised in the very first step, outside the scope of your Seaside handling code.

At first sight, I would not immediately know how this can be solved.

Note that in order to know how much is coming in, you have to read it, but you have to stop in time. Note also that the content-length header could be absent or wrong (a malicious request).

I can't remember where we currently stand on a streaming Zn Seaside adaptor, there were some experiments in the past IIRC. That could be a solution, because then the entity/body is not read until further down the line, if we can get it to work. The current one only seems to do streaming for responses.

Sven

> On 19 Jan 2017, at 13:32, Bernhard Pieber <[hidden email]> wrote:
>
> I have a Seaside application which includes a file upload feature.
>
> renderContentOn: html
> …
> html fileUpload
> callback: [ :file | self receiveFile: file ].
> html submitButton: 'Upload‘ ]
> …
>
> In receiveFile: I just save the uploaded file on the file system.
>
> When I upload a file larger than 16 MB an error page is shown with the error message:
> Bad Request ZnEntityTooLarge
>
> I found that by using ZnConstants>>maximumEntitySize: I can increase this limit. However, I want to catch this in the image and show an error message to the user.
>
> I tried wrapping receiveFile: and renderContentOn: with an on:do: exception handler for ZnEntityTooLarge. However, neither works. It seems that the error happens before renderContentOn: is even called. I searched the mailing lists but did not come up with an answer.
>
> How can I achieve this in Seaside? Any help would be much appreciated.
>
> Cheers,
> Bernhard
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
bpi
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-users] Bad Request ZnEntityTooLarge

bpi
Thank you for your answer, Sven.

That’s a bummer. If I understand you correctly, currently there is no hook in Seaside to catch lower level server exceptions (like ZnEntityTooLarge) to show a nice looking error page, e.g. „You are trying to upload a file that’s too large. Don’t do that!“ Really? :-/

Cheers,
Bernhard

> Am 19.01.2017 um 14:29 schrieb Sven Van Caekenberghe <[hidden email]>:
>
> Hi Bernard,
>
> Your analysis is correct.
>
> Most Seaside adaptors, including ZnZincServerAdaptor, are implemented so that the incoming (Zn) request is read from the wire, then converted to Seaside WA* objects, processed, the result converted from WA* objects to an outgoing (Zn) response and put on the wire.
>
> Zn has some built-in resource protection measures, including a limit on how large entities (bodies) can be. The error of crossing such a limit is raised in the very first step, outside the scope of your Seaside handling code.
>
> At first sight, I would not immediately know how this can be solved.
>
> Note that in order to know how much is coming in, you have to read it, but you have to stop in time. Note also that the content-length header could be absent or wrong (a malicious request).
>
> I can't remember where we currently stand on a streaming Zn Seaside adaptor, there were some experiments in the past IIRC. That could be a solution, because then the entity/body is not read until further down the line, if we can get it to work. The current one only seems to do streaming for responses.
>
> Sven
>
>> On 19 Jan 2017, at 13:32, Bernhard Pieber <[hidden email]> wrote:
>>
>> I have a Seaside application which includes a file upload feature.
>>
>> renderContentOn: html
>> …
>> html fileUpload
>> callback: [ :file | self receiveFile: file ].
>> html submitButton: 'Upload‘ ]
>> …
>>
>> In receiveFile: I just save the uploaded file on the file system.
>>
>> When I upload a file larger than 16 MB an error page is shown with the error message:
>> Bad Request ZnEntityTooLarge
>>
>> I found that by using ZnConstants>>maximumEntitySize: I can increase this limit. However, I want to catch this in the image and show an error message to the user.
>>
>> I tried wrapping receiveFile: and renderContentOn: with an on:do: exception handler for ZnEntityTooLarge. However, neither works. It seems that the error happens before renderContentOn: is even called. I searched the mailing lists but did not come up with an answer.
>>
>> How can I achieve this in Seaside? Any help would be much appreciated.
>>
>> Cheers,
>> Bernhard
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-users] Bad Request ZnEntityTooLarge

Johan Brichau-2
Hi Bernhard,

imho, it’s better practice to detect too large file upload in your app on the client side, i.e. before your user has been uploading xxx MB. For that, you can check out various client-side programs like jQuery-FileUpload (https://blueimp.github.io/jQuery-File-Upload/)

You also might want to check out this: http://jbrichau.github.io/blog/large-file-upload-in-seaside
And Nick’s original post has come back online since I wrote mine too: http://nickager.com/blog/2011/07/01/File-upload-using-Nginx-and-Seaside

The adaptor framework was built to minimize dependencies between Seaside and the http server. To make Seaside aware about an error occurring inside the http server, and allow to produce a response to it, a specialized extension of the adaptor is necessary. I think you _can_ make a nice looking page using Seaside when you tell Zinc that it should respond to the error using Seaside. Both Zinc and Seaside are frameworks and you can customize them by specializing appropriate methods. If you create your own ZnSeasideServerAdaptorDelegate and override #handleRequest: to catch the error, you can dispatch to the Seaside framework to render a nice looking page. 

There are several ways to dispatch back to Seaside. The easiest way would be to generate a generic page using the WABuilder:

WAHtmlCanvas builder render: [ :html | html text: ‘Oops… entity too large!’ ]

However, that does not dispatch back to your running app and you probably expect to be able to specify some other callback in your Seaside code that would execute on that error? This would make your app dependent on Zinc though (and the Seaside framework would need be extended to handle that additional dependency on adaptors). Not sure if all that work makes sense when this kind of upload error is preferably handled differently.

cheers
Johan


On 20 Jan 2017, at 07:04, Bernhard Pieber <[hidden email]> wrote:

Thank you for your answer, Sven.

That’s a bummer. If I understand you correctly, currently there is no hook in Seaside to catch lower level server exceptions (like ZnEntityTooLarge) to show a nice looking error page, e.g. „You are trying to upload a file that’s too large. Don’t do that!“ Really? :-/

Cheers,
Bernhard

Am 19.01.2017 um 14:29 schrieb Sven Van Caekenberghe <[hidden email]>:

Hi Bernard,

Your analysis is correct.

Most Seaside adaptors, including ZnZincServerAdaptor, are implemented so that the incoming (Zn) request is read from the wire, then converted to Seaside WA* objects, processed, the result converted from WA* objects to an outgoing (Zn) response and put on the wire.

Zn has some built-in resource protection measures, including a limit on how large entities (bodies) can be. The error of crossing such a limit is raised in the very first step, outside the scope of your Seaside handling code.

At first sight, I would not immediately know how this can be solved.

Note that in order to know how much is coming in, you have to read it, but you have to stop in time. Note also that the content-length header could be absent or wrong (a malicious request).

I can't remember where we currently stand on a streaming Zn Seaside adaptor, there were some experiments in the past IIRC. That could be a solution, because then the entity/body is not read until further down the line, if we can get it to work. The current one only seems to do streaming for responses.

Sven

On 19 Jan 2017, at 13:32, Bernhard Pieber <[hidden email]> wrote:

I have a Seaside application which includes a file upload feature.

renderContentOn: html

html fileUpload
callback: [ :file | self receiveFile: file ].
html submitButton: 'Upload‘ ]


In receiveFile: I just save the uploaded file on the file system.

When I upload a file larger than 16 MB an error page is shown with the error message:
Bad Request ZnEntityTooLarge

I found that by using ZnConstants>>maximumEntitySize: I can increase this limit. However, I want to catch this in the image and show an error message to the user.

I tried wrapping receiveFile: and renderContentOn: with an on:do: exception handler for ZnEntityTooLarge. However, neither works. It seems that the error happens before renderContentOn: is even called. I searched the mailing lists but did not come up with an answer.

How can I achieve this in Seaside? Any help would be much appreciated.

Cheers,
Bernhard
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
bpi
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-users] Bad Request ZnEntityTooLarge

bpi
Hi Johan,

Thank you for your detailed answer. See below.
> Am 20.01.2017 um 10:12 schrieb Johan Brichau <[hidden email]>:
>
> imho, it’s better practice to detect too large file upload in your app on the client side, i.e. before your user has been uploading xxx MB. For that, you can check out various client-side programs like jQuery-FileUpload (https://blueimp.github.io/jQuery-File-Upload/)
Thanks for the pointer. I will look into adding somthing like this on the client side. Someone mentioned using Dropzone.js from Seaside. I had searched stackoverflow for limiting upload file size and found some helpful tips:
http://stackoverflow.com/questions/11514166/check-file-size-before-upload

However, I also found warnings like these:
„Keep in mind that even if it's now possible to validate on the client, you should still validate it on the server, though. All client side validations can be bypassed.“
„Of course, this … can be tampered with so always use server side validation.“

This is why I wanted to find a user-friendly way to prevent this from my server code. Are you saying, this is not necessary in your opinion?

> You also might want to check out this: http://jbrichau.github.io/blog/large-file-upload-in-seaside
> And Nick’s original post has come back online since I wrote mine too: http://nickager.com/blog/2011/07/01/File-upload-using-Nginx-and-Seaside
Yes, I had seen this. In my case I have to use Apache, which is configured by someone else. Do you know if anyone has done this for Apache?

> The adaptor framework was built to minimize dependencies between Seaside and the http server. To make Seaside aware about an error occurring inside the http server, and allow to produce a response to it, a specialized extension of the adaptor is necessary. I think you _can_ make a nice looking page using Seaside when you tell Zinc that it should respond to the error using Seaside. Both Zinc and Seaside are frameworks and you can customize them by specializing appropriate methods. If you create your own ZnSeasideServerAdaptorDelegate and override #handleRequest: to catch the error, you can dispatch to the Seaside framework to render a nice looking page.
Thanks for the tip. I tried this. However, I cannot catch ZnEntityTooLarge in handleRequest, because Zinc handles it before.

Maybe Kom would work.

> There are several ways to dispatch back to Seaside. The easiest way would be to generate a generic page using the WABuilder:
>
> WAHtmlCanvas builder render: [ :html | html text: ‘Oops… entity too large!’ ]
>
> However, that does not dispatch back to your running app and you probably expect to be able to specify some other callback in your Seaside code that would execute on that error?
Well, ideally I could catch that exception, update some domain object, and refresh the page where the upload originated from.

> This would make your app dependent on Zinc though (and the Seaside framework would need be extended to handle that additional dependency on adaptors).
I am not sure I understand. Wouldn’t it be possible to have a common API between adaptor and server which allows for streaming uploads?

Being able to write something like this sure would be nice:

html fileUpload
        streaming: true;
        callback: [:stream | … ].

> Not sure if all that work makes sense when this kind of upload error is preferably handled differently.
Good point.

> cheers
> Johan
>
>
>> On 20 Jan 2017, at 07:04, Bernhard Pieber <[hidden email]> wrote:
>>
>> Thank you for your answer, Sven.
>>
>> That’s a bummer. If I understand you correctly, currently there is no hook in Seaside to catch lower level server exceptions (like ZnEntityTooLarge) to show a nice looking error page, e.g. „You are trying to upload a file that’s too large. Don’t do that!“ Really? :-/
>>
>> Cheers,
>> Bernhard
>>
>>> Am 19.01.2017 um 14:29 schrieb Sven Van Caekenberghe <[hidden email]>:
>>>
>>> Hi Bernard,
>>>
>>> Your analysis is correct.
>>>
>>> Most Seaside adaptors, including ZnZincServerAdaptor, are implemented so that the incoming (Zn) request is read from the wire, then converted to Seaside WA* objects, processed, the result converted from WA* objects to an outgoing (Zn) response and put on the wire.
>>>
>>> Zn has some built-in resource protection measures, including a limit on how large entities (bodies) can be. The error of crossing such a limit is raised in the very first step, outside the scope of your Seaside handling code.
>>>
>>> At first sight, I would not immediately know how this can be solved.
>>>
>>> Note that in order to know how much is coming in, you have to read it, but you have to stop in time. Note also that the content-length header could be absent or wrong (a malicious request).
>>>
>>> I can't remember where we currently stand on a streaming Zn Seaside adaptor, there were some experiments in the past IIRC. That could be a solution, because then the entity/body is not read until further down the line, if we can get it to work. The current one only seems to do streaming for responses.
>>>
>>> Sven
>>>
>>>> On 19 Jan 2017, at 13:32, Bernhard Pieber <[hidden email]> wrote:
>>>>
>>>> I have a Seaside application which includes a file upload feature.
>>>>
>>>> renderContentOn: html
>>>> …
>>>> html fileUpload
>>>> callback: [ :file | self receiveFile: file ].
>>>> html submitButton: 'Upload‘ ]
>>>> …
>>>>
>>>> In receiveFile: I just save the uploaded file on the file system.
>>>>
>>>> When I upload a file larger than 16 MB an error page is shown with the error message:
>>>> Bad Request ZnEntityTooLarge
>>>>
>>>> I found that by using ZnConstants>>maximumEntitySize: I can increase this limit. However, I want to catch this in the image and show an error message to the user.
>>>>
>>>> I tried wrapping receiveFile: and renderContentOn: with an on:do: exception handler for ZnEntityTooLarge. However, neither works. It seems that the error happens before renderContentOn: is even called. I searched the mailing lists but did not come up with an answer.
>>>>
>>>> How can I achieve this in Seaside? Any help would be much appreciated.
>>>>
>>>> Cheers,
>>>> Bernhard
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
bpi
Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-users] Bad Request ZnEntityTooLarge

bpi
> Am 21.01.2017 um 15:12 schrieb Ben Coman <[hidden email]>:
> On Sat, Jan 21, 2017 at 1:22 AM, Bernhard Pieber <[hidden email]> wrote:
> Hi Johan,
>
> Thank you for your detailed answer. See below.
> > Am 20.01.2017 um 10:12 schrieb Johan Brichau <[hidden email]>:
> >
> > imho, it’s better practice to detect too large file upload in your app on the client side, i.e. before your user has been uploading xxx MB. For that, you can check out various client-side programs like jQuery-FileUpload (https://blueimp.github.io/jQuery-File-Upload/)
> Thanks for the pointer. I will look into adding somthing like this on the client side. Someone mentioned using Dropzone.js from Seaside. I had searched stackoverflow for limiting upload file size and found some helpful tips:
> http://stackoverflow.com/questions/11514166/check-file-size-before-upload
>
> However, I also found warnings like these:
> „Keep in mind that even if it's now possible to validate on the client, you should still validate it on the server, though. All client side validations can be bypassed.“
> „Of course, this … can be tampered with so always use server side validation.“
>
> This is why I wanted to find a user-friendly way to prevent this from my server code. Are you saying, this is not necessary in your opinion?
>
>
> In general I'd say... If someone is smart-enough and wicked enough to bypass your client side checks, you don't need to be user-friendly to them.  The server checks are more to protect your server from them.
You are right. I am convinced. I will add client side checks. Thanks for your answer, Ben.

Cheers,
Bernhard
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside