Expand my Community achievements bar.

SOLVED

Dispatcher returns 400 for anonymous POST request

Avatar

Level 2

AEM 6.5.18

Problem statement: Trying to save PDF in AEM publish DAM and return a externalized PDF URL.

A post servlet is created to POST data with pdf as blobdata to store PDF in DAM. If directly posted to AEM publish, PDF is stored in DAM successfully. 

However, if it is posted via dispatcher, we observe 400 - Bad request error. 

Things checked/observed:
Enabled trace logs in dispatcher and ensured filter allows POST for servlet path.
Since it is anonymous POST, no CSRF-TOKEN is generated.
All /clientheaders required are allowed in dispatcher
Tried adding LimitRequestBody  LimitRequestFieldSize LimitRequestFields LimitRequestLine to sufficient size
Tried to disable mod_security to see if the multipart data is allowed to be posted to narrow root cause.

Above did not resolve the issue and unable to determine the root cause of 400-bad request in dispatcher alone.

Please let me know if any further inputs I missed to share. Kindly let know any pointers and if the data sent using frontend is incorrect.

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @nsriram 

A "Bad Request" usually has to do something with wrong or missing HTTP headers.

Can you check which headers the request has when it hits the CQ instance (after being processed by the dispatcher)?

 

Please check : https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/dispatcher-issue/m-p/22941... 

 

 



Arun Patidar

View solution in original post

8 Replies

Avatar

Level 3

Hi @nsriram ,

It would be great if you can add info like whether Api  reaches to code or getting returned from dispatcher itself.

Thanks,

Avatar

Level 2

Hi @MukeshYadav_ ,

Request does not reach the servlet via dispatcher. It is allowed in filter but response is 400 from dispatcher. If directly posted to AEM publish, response status is 200 and PDF is inserted into DAM. Below is what is being tried from frontend

 

ajax
$.ajax({
    url: <servlet_path>,
    data: formData,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function(response){
        // process response
    }
});

fetch
const response = await fetch('<servlet_path>', {
    method: 'POST',
    body: formData
});

 

Avatar

Correct answer by
Community Advisor

Hi @nsriram 

A "Bad Request" usually has to do something with wrong or missing HTTP headers.

Can you check which headers the request has when it hits the CQ instance (after being processed by the dispatcher)?

 

Please check : https://experienceleaguecommunities.adobe.com/t5/adobe-experience-manager/dispatcher-issue/m-p/22941... 

 

 



Arun Patidar

Avatar

Level 2

Hi @arunpatidar 
Trace from dispatcher logs where some request headers seem repeated 

[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] Found farm publishfarm for ****
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] checking [/bin/<servlet_path>]
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] request URL has no extension: /bin/<servlet_path>
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] cache-action for [/bin/<servlet_path>]: NONE
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] Decomposing URL :
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] uri : /bin/<servlet_path>
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] suffix : No suffix 
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] extension : No extension 
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] selector : No selectors 
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] Decomposing Complete
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] Filter rule entry /000x allowed 'POST /bin/<servlet_path> HTTP/1.1'
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] Creating new connection: x.x.x.x:4503
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] Connected to backend 0 (x.x.x.x:4503)
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.uri = "/bin/<servlet_path>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[X-Forwarded-Proto] = "https"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[referer] = "<domain>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[user-agent] = "<useragent_value>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[content-type] = "multipart/form-data; boundary=----WebKitFormBoundaryIZt2HmdATCVOIlf5"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[content-length] = "13645"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[accept-encoding] = "gzip, deflate, br, zstd"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[accept-language] = "en-GB,en-US;q=0.9,en;q=0.8"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[accept] = "*/*"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[host] = "<domain>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[cookie] = "<cookie_values>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[Connection] = "keep-alive"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[Sec-Fetch-Dest] = "empty"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[Sec-Fetch-Mode] = "cors"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[Sec-Fetch-Site] = "same-origin"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[sec-ch-ua] = ""Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126""
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[sec-ch-ua-mobile] = "?0"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[sec-ch-ua-platform] = ""macOS""
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[x-dtpc] = "1$586353623_54h15vUBJEBRCPUUVAUORFLLUPPHWWTFGCTPTT-0e0"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[X-Forwarded-Proto] = "https"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[referer] = "<domain>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[user-agent] = "<useragent_value>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[content-type] = "multipart/form-data; boundary=----WebKitFormBoundaryIZt2HmdATCVOIlf5"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[content-length] = "13645"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[accept-encoding] = "gzip, deflate, br, zstd"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[accept-language] = "en-GB,en-US;q=0.9,en;q=0.8"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[accept] = "*/*"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[host] = "<domain>"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[cookie] = "
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[Via] = "1.1 <domain> (dispatcher)"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[X-Forwarded-For] = "IPs"
[Fri Jun 21 xx:xx:xx 2024] [T] [pid xxxxxx] request.headers[Server-Agent] = "Communique-Dispatcher"
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] Sending request body to remote server
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] Request body sent to remote server
[Fri Jun 21 xx:xx:xx 2024] [D] [pid xxxxxx] No socket reuse: neither GET nor HEAD
[Fri Jun 21 xx:xx:xx 2024] [I] [pid xxxxxx] "POST /bin/<servlet_path>" 400 none [publishfarm/0] 3ms

Avatar

Level 2

Hi @arunpatidar 
My /clientheaders include all of these in dispatcher. Kindly let me know if you see an issue here

Avatar

Level 2

Hi @arunpatidar ,

Thanks a lot for your pointer. I had included clientheaders like below

 

/clientheaders {
	$include "/etc/httpd/conf.dispatcher.d/clientheaders/ams_common_clientheaders.any"
	$include "/etc/httpd/conf.dispatcher.d/clientheaders/<project>_clientheaders.any"
}

 

 with AMS commonly allowed headers copied over to project specific headers. So I had duplicated clientheaders allowed. When I merged the file and only called my project specific clientheader file, it worked! So it is duplicated clientheaders that was causing 400.

Avatar

Level 5

contentType false will remove any content type header which could be a possible cause for dispatcher to block it. Could you try to remove it once from the ajax call just to test ? 
Also there should be some clue in Apache's or dispatcher error logs if this is really getting blocked at the dispatcher level.

Avatar

Level 2

Hi @h_kataria 

I also tried using fetch as posted above.

When using AJAX to send multipart/form-data (such as for file uploads) with jQuery, you typically need to set the contentType to false. This ensures that the correct content type is set automatically by the browser, including the multipart boundary. Additionally, you need to set processData to false to prevent jQuery from attempting to process the data into a query string, which is not suitable for FormData objects.

Reference:
GenAI, https://api.jquery.com/jQuery.ajax/