86

I'm looking into a restful design and would like to use the HTTP methods (POST, GET, ...) and HTTP headers as much as possible. I already found out that the HTTP methods PUT and DELETE are not supported from the browser.

Now I'm looking to get different representations of the same resource and would like to do this by changing the Accept header of the request. Depending on this Accept header, the server can serve a different view on the same resource.

Problem is that I didn't find a way to tell my browser to change this header.

The <a..> tag has a type attribute, that can have a mime type, looked like a good candidate but the header was still the browser default (in Firefox it can be changed in about:config with the network.http.accept.default key).

user66001
  • 774
  • 1
  • 13
  • 36
Jeroen Wyseur
  • 3,413
  • 3
  • 19
  • 16
  • I hear you. It would be great to hardcode some headers and in your browser tab just visit URLs to test your code. I don't want a full-blown separate interface like the Chrome Postman app. – Sridhar Sarnobat Oct 19 '16 at 00:27
  • 1
    This extension works quite nicely for me: https://chrome.google.com/webstore/detail/modify-headers-for-google/innpjfdalfhpcoinfnehdnbkglpmogdi?hl=en-US – Sridhar Sarnobat Oct 19 '16 at 23:35
  • Possible duplicate of https://stackoverflow.com/q/3274144/816213 – Sachin Jain Apr 06 '23 at 07:05
  • @SachinJain So my 4 year old question is a duplicate of a 4 day old one? Seems to me it would be the other way round .... – Jeroen Wyseur Apr 07 '23 at 10:07
  • ModHeader works for me: https://chrome.google.com/webstore/detail/modheader-modify-http-hea/idgpnmonknjnojddfkpgkljpfnnfcklj – Ben Ketteridge Jul 21 '23 at 15:10

6 Answers6

47

I would partially disagree with Milan's suggestion of embedding the requested representation in the URI.

If anyhow possible, URIs should only be used for addressing resources and not for tunneling HTTP methods/verbs. Eventually, specific business action (edit, lock, etc.) could be embedded in the URI if create (POST) or update (PUT) alone do not serve the purpose:

POST http://shonzilla.com/orders/08/165;edit

In the case of requesting a particular representation in URI you would need to disrupt your URI design eventually making it uglier, mixing two distinct REST concepts in the same place (i.e. URI) and making it harder to generically process requests on the server-side. What Milan is suggesting and many are doing the same, incl. Flickr, is exactly this.

Instead, a more RESTful approach would be using a separate place to encode preferred representation by using Accept HTTP header which is used for content negotiation where client tells to the server which content types it can handle/process and server tries to fulfill client's request. This approach is a part of HTTP 1.1 standard, software compliant and supported by web browsers as well.

Compare this:

GET /orders/08/165.xml HTTP/1.1
or
GET /orders/08/165&format=xml HTTP/1.1

to this:

GET /orders/08/165 HTTP/1.1
Accept: application/xml

From a web browser you can request any content type by using setRequestHeader method of XMLHttpRequest object. For example:

function getOrder(year, yearlyOrderId, contentType) {
 var client = new XMLHttpRequest();
 client.open("GET", "/order/" + year + "/" + yearlyOrderId);
 client.setRequestHeader("Accept", contentType);
 client.send(orderDetails);
}

To sum it up: the address, i.e. the URI of a resource should be independent of its representation and XMLHttpRequest.setRequestHeader method allows you to request any representation using the Accept HTTP header.

Cheers!
Shonzilla

Shonzilla
  • 7,926
  • 1
  • 23
  • 25
  • 3
    A disadvantage is that it is impossible to (hyper)link directly to say the `XML` resource. For some applications this might be needed. For example in OpenCPU, graphics can be retrieved in `PNG`, `PDF` or `SVG` format. However, it would be impossible to embed the `PNG` image in a HTML page if an `Accept` header is required for retrieval. – Jeroen Ooms Mar 02 '14 at 00:03
  • 3
    @Jeroen: if the browser supports SVG better than PNG then it should send an Accept header with SVG weighted higher than PNG and respond with SVG. For browsers that don't support SVG, their Accept header wouldn't contain application/svg+xml so the server would send back the PNG. If for some reason you consider the PNG version to have higher fidelity than the PDF/SVG version (e.g. vector-traced photograph), then the server should set a higher weight for the PNG version so that it would be returned if the browser supports all three equally. This is how content negotiation is supposed to work. – Lie Ryan Apr 22 '14 at 19:39
  • 1
    This response almost convinced me but later I saw [this response](http://programmers.stackexchange.com/a/251555/216886) on the similar topic and I tend to agree with the latter. In many (or majority of) cases the format information is really a part of the resource identity and can (or should) be include in the URI in order to avoid unexpected results after sharing such an URI between different clients. It these cases the Accepts header should play a secondary role. It is important to distinguish these cases. – ps_ttf May 10 '16 at 16:12
12

I was looking to do exactly the same thing (RESTful web service), and I stumbled upon this firefox addon, which lets you modify the accept headers (actually, any request headers) for requests. It works perfectly.

https://addons.mozilla.org/en-US/firefox/addon/967/

Chris
  • 121
  • 1
  • 2
  • Chris, what if the extension has a bug, or the extension does not work with the browser version you'd like or if the developers simply stopped updating the extensions ? I see this happening for most, if not all Firefox extensions which let you add/modify request headers. Add ons might be easy & make you productive, but won't work when there are issues with the extensions. – MasterJoe Dec 28 '17 at 00:47
  • 1
    There's this one for Chrome https://chrome.google.com/webstore/detail/modify-headers-for-google/innpjfdalfhpcoinfnehdnbkglpmogdi – Nhan May 16 '18 at 00:49
  • firefox & chrome addons are no longer active – JRichardsz Nov 26 '20 at 20:55
8

I don't think it's possible to do it in the way you are trying to do it.

Indication of the accepted data format is usually done through adding the extension to the resource name. So, if you have resource like

/resources/resource

and GET /resources/resource returns its HTML representation, to indicate that you want its XML representation instead, you can use following pattern:

/resources/resource.xml

You have to do the accepted content type determination magic on the server side, then.

Or use Javascript as James suggests.

Milan Novota
  • 15,506
  • 7
  • 54
  • 62
7

ModHeader extension for Google Chrome, is also a good option. You can just set the Headers you want and just enter the URL in the browser, it will automatically take the headers from the extension when you hit the url. Only thing is, it will send headers for each and every URL you will hit so you have to disable or delete it after use.

Jai Prak
  • 2,855
  • 4
  • 29
  • 37
  • It works fine. and the [here](https://bewisse.com/modheader/headers/) you can get your request header conveniently. – ramwin Jan 28 '21 at 01:41
0

Use some javascript!

xmlhttp=new XMLHttpRequest();
xmlhttp.open('PUT',http://www.mydomain.org/documents/standards/browsers/supportlist)
xmlhttp.send("page content goes here");
James Anderson
  • 27,109
  • 7
  • 50
  • 78
  • 1
    Thank you for the fast answer but the question is about changing the default headers send in the HTTP request. In particular the Accept header. – Jeroen Wyseur Dec 17 '08 at 15:45
  • On a side note, the specification (http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/#dfn-open) says nothing about PUT and DELETE, see the editorial note. Also, there is no submit in that case what is nice a ajaxified user interface but otherwise not. – Jeroen Wyseur Dec 17 '08 at 15:46
0

Possible solutions

As mentioned in the answer from Shonzilla and Milan you can get the resource format that you want by either

  1. changing the values in the Accept header of the request or
  2. explicitly mentioning the file format in the URI (as an extension or in the query param)

Enforcing these solutions in your browser

But trying to do this by changing the browser config is not a flexible solution. And you can only override the default behavior for method 1. I am not really aware of how one would implement the second case via the config.

There are extensions that let you add headers and some that let you modify the URL. But Requestly lets you do all of this with a lot of flexibility

PS: I am one of the maintainers of Requestly https://github.com/requestly/requestly

Adding Accept Header

Create a header rule that overrides the Accept request header to your desired value.

header rule for Accept header override

If you want to do this for all your request use the wildcard * or you can specify specific matching parameters like this

URI modification

For the URI modification approach, either create a simple redirect for a specific request

simple redirect rule

or use a complex regex match like this to apply the rule for the specific resource types that you want

complex redirect to change URI extension

If the server requires mime type to be sent as a query param (this very much depends on the implmentation) for eg, in the key format, you can create a query param rule

query param add format

nsrCodes
  • 625
  • 10
  • 25