GET working fine where POST in not working XMLHttpRequest - javascript

My GET request is working fine and responding as xml.
https://mydomain.com/mypage.php?id=123&nm=ak_dhara
Note: our php page is on https.
But POST is not working.
xhttp.open("POST"," https://mydomain.com/mypage.php",true);
xhttp.setRequestHeader("Content-type","application/xhtml+xml");
xhttp.send("id=123&nm=ak_dhara");
Any Suggestion ?

xhttp.setRequestHeader("Content-type","application/xhtml+xml") is wrong. If you want to ask for XHTML content, then the right request header name is Accept. If you want to identify the type of content that you're sending, then you're sending application/x-www-form-urlencoded. A server that respects the headers will try to read the data that you sent, id=123&nm=ak_dhara, as a special kind of request encoded using the application/xhtml+xml format; and no PHP server knows how to do that. It might work in certain browsers because they know that's not a valid content type, and they ignore that header and send the correct value anyway.
By the way, application/x-www-form-urlencoded is the default one, so you don't have to set it explicitly.

Related

Are application/x-www-form-urlencoded and multipart/form-data the only 2 special content types treated by the client when sending data to server?

I used to search and read posts related to this topic but now I am a little bit confused again.
As before, I read many posts but still didn't see any post clearly clarifying how these different content type would affect or maniuplate the client's data, when the client is sending data to server.
So here's my understanding (assume it's a POST method):
There are 2 content types are special and treated differently from the rest.
application/x-www-form-urlencoded and multipart/form-data.
with application/x-www-form-urlencoded, the client's data is encoded (changed) in some ways.
with multipart/form-data, the client will use something called boundary as a delimiter. As a result, the client can send many stuffs all together in a single request with some boundary string inserted as delimiters.
And for all the other content types specified by the client (xmlhttp.setRequestHeader) , e.g. application/json, application/pdf, application/image, application/octet-stream blablabla, the client won't change anything but just put the raw (binary) data in the http request body and send it to the server. The server can retrieve the raw data from the http request body and do whatever it wants.
Is my understanding/classfication correct?
By saying "client", I mean browser mostly.
By saying "server", I mean the server framework or applicaiton.
Because if I understand correctly, the web server e.g. Nginx or Apache won't do anything to the data. They just pass the data to the server-side application connected to them.
There are 2 content types are special and treated differently from the rest.
No. Those 2 content types (and text/plain which is pointless and you should never use) are supported by HTML forms.
with application/x-www-form-urlencoded, the client's data is encoded (changed) in some ways.
With a regular HTML form, all the encodings change the data in some way (even if it is text/plains "Make everything be name=value and shove a new line between each item).
with multipart/form-data, the client will use something called boundary as a delimiter.
Yes. text/plain uses a new line. application/x-www-form-urlencoded uses a &. Everything has a delimiter. (You just can't tell the delimiter apart of a new line in the data in text/plain which is what makes it useless).
As a result, the client can send many stuffs all together in a single request with some boundary string inserted as delimiters.
The client can send many things with any of those three encodings.
The different is that multipart supports files.
Multipart lets you put headers before the data for each part, so you can include things like filenames and content-types which are almost essential for supporting files.
And for all the other content types specified by the client (xmlhttp.setRequestHeader) , e.g. application/json, application/pdf, application/image, application/octet-stream blablabla, the client won't change anything but just put the raw (binary) data in the http request body and send it to the server.
Explicitly setting a content type has no effect on what the XMLHttpRequest object will do with what you pass to send().
If you pass a string, it will not encode that in any way (so you need to encode the data into the string yourself and set the right content-type header for the encoding you picked). If you pass a FormData object then it will encode it as multipart. etc.
Because if I understand correctly, the web server e.g. Nginx or Apache won't do anything to the data. They just pass the data to the server-side application connected to them.
That's generally the case, but somewhat oversimplified. e.g. There may be no distinction between the server and the server-side application if it is written using Express.js running on Node.js.
Summary
Forms always encode the data. The enctype attribute tells them which way to do it.
XMLHttpRequest and fetch may encode the data, but it depends on what kind of value you pass to them. If it is a string, you have to encode it and set the right Content-Type yourself.

How to respond with HTML or JSON depending on the request in Sails.js

Let's say I have a model called User with its basic REST CRUD (GET, POST, DELETE, UPDATE).
When I go to user/4 (where 4 is an ID of a User that doesn't exist), there are two cases:
If I'm doing it with a REST client like Postman, I'd get a 404 and nothing else.
If I'm on the browser, I'll get a 404 page (with text, images, etc), which is defined in the views folder.
How can I achieve this for findOne, find, and other URLs? I want to be able to have JSON-only responses, and HTML pages responses for different types of requests. But I don't want to override the functions, because the ORM is already doing a lot of work that I don't want to lose.
EDIT: My solution would be to leave the API with a prefix, such as /api/user/4 and the HTML response without the prefix user/4, but I'd like to see more elegant solutions.
EDIT 2: I just decided to go all JSON, and use a REST service only with an independent front end ;)
If you have control over the headers sent by the API client, I see two clean semantic solutions, based on the headers sent :
you could rely on the X-Requested-With: XMLHttpRequest header to recognize Ajax queries
rely on a Accept: text/json header to explicitly request json
You could also modify the url with file extensions to request a specific response, user/4.html => send html, user/4 => send json.

two questions about content-type

New to XMLHttpRequest, and here is some confusion for me:
Why must we set the content type when using the post method in a xmlhttprequest?
XHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
Isnt the default value application/x-www-form-urlencoded already?
Here is also one tool which help you for passing parameters via application/x-www-form-urlencoded. https://www.browserling.com/tools/url-encode. Also i suggest you to use Postman tool first to check the API response and then use Ajax call in JS
Why must we set the content type when using the post method in a xmlhttprequest?
XHR.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
HTTP/POST does not ask for that specific content-type when you do a HTTP/POST over AJAX (or for that matter via other means). It is up to you (and up to the server side program handling it). Read the second section for Why we must set it explicitly.
Very often, we serialise the form (percentile-encode it -- a=b&c=d format) and send it across to the server. This format is application/x-www-form-urlencoded. If you are sending an XML, you would use application/xml, for JSON you would use application/json and so on.
As for GET request, there's no body and hence we dont really need the content-type header.
Isnt the default value application/x-www-form-urlencoded already?
I tried skimming through here for the default content-type header. I couldn't find anything. However, when I tried doing a HTTP/POST AJAX request via chrome's console, I noticed that chrome's default is application/xml.
Just a piece of advice -- never rely on default behaviour except when its explicitly stated and/or is a part of the standard. Why not set the content type explicitly?

Http-Method changes from POST to OPTIONS when changing Content-Type

I am using closure library to do a simple POST. I think XhrIo should work because from my machine when I use any other rest client ,like Firefox browser app RESTClient or Chrome's Simple Rest Client , I can make POST request to the server and content type is application/json.
But from my application I am unable to make a post.
I am using the following code
xhr = new goog.net.XhrIo;
xhr.send('http://myhost:8181/customer/add','POST', goog.json.serialize(data));
If I leave the headers default, I get this
Encoding: UTF-8
Http-Method: POST
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
If I try to change the header by passing {'content-type':'application/json'} as 4th parameter, header changes to
Http-Method: OPTIONS
Content-Type:
Shouldn't I be able to change headers appropriately with Closure library just as RESTClient does with XMLHttpRequest using JQuery ?
How else can the header be altered to make it appear like this
Encoding: UTF-8
Http-Method: POST
Content-Type: application/json;charset=UTF-8
Appreciate any help
Eddie
When you add a header to an XHR object, most browsers will do a preflight request, which is the OPTIONS method that you are seeing. There is not a way to circumvent this if you are adding custom headers, unfortunately. The POST will be sent after the OPTIONS.
This article explains the OPTIONS request a bit. I ran into issues with the preflight a while back, if that is any help.
If you have specific issues with the OPTIONS request you should edit your question to include them; otherwise, this is expected behavior.
FWIW mine also failed to update the type when I specified...
{'content-type':'application/json'}
However, if I corrected the case to
{'Content-Type':'application/json'}
... it worked.
Go figure.
If you are pass Content-Type on authorization request it will convert POST method to OPTIONS method so while we are use ouath and passing authorization token that time do not required Content-Type.
So do not pass Content-Type on all authorization request it won't change your method POST to OPTIONS

It is different to Javascript, getting JSON as "text/html" and as "file"?

In JavaScript I get JSON data. The service sends me back JSON data in a file (HTTP Header - file), a second service sends me back data as text in browser (HTTP Header type - text/html).
I need to parse this data in JavaScript (ExtJS).
It is different to Javascript, getting JSON as text/html and as file?
I know that with text/html - all works fine, but will it work with other HTTP Header type (that retrieves file that contains JSON)?
Thanks
If your response content-type is text/html you should be fine, as long as you parse the response with something like JSON.parse (see json2.js for older browsers that don't have this natively) it should be fine.
In fact, if you're loading your response from an iframe - IE will prompt you to download a file if your response is application/json. This should only be an issue if you're attempting a file upload without refreshing the page though.
To be honest I've never tried with other header types. I would imagine text/plain could work, however you may run into the IE iframe download issue above.
My recommendation would be to use application/json if you can, however failing this text/html should suffice
It should be application/json.
If it is anything else, it might break clients that try to detect the result type automatically. But if a client expects JSON, they will probably ignore the header anyway.

Categories

Resources