[Seaside] [Pharo-users] Bad Request ZnEntityTooLarge

Bernhard Pieber bernhard at pieber.com
Fri Jan 20 17:22:55 UTC 2017

Hi Johan,

Thank you for your detailed answer. See below.
> Am 20.01.2017 um 10:12 schrieb Johan Brichau <johan at inceptive.be>:
> 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:

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 <bernhard at pieber.com> 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 <sven at stfx.eu>:
>>> 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 <bernhard at pieber.com> 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

More information about the seaside mailing list