35

Recently I run into some weird issue with http header usage ( Adding multiple custom http request headers mystery) To avoid the problem at that time, I have put the fields into json string and add that json string into header instead of adding those fields into separate http headers.

For example, instead of

request.addHeader("UserName", mUserName);
request.addHeader("AuthToken", mAuthorizationToken);
request.addHeader("clientId","android_client");

I have created a json string and add it to the single header

String jsonStr="{\"UserName\":\"myname\",\"AuthToken\":\"123456\",\"clientId\":\"android_client\"}";
request.addHeader("JSonStr",jsonStr);

Since I am new to writing Rest and dealing with the Http stuff, I don't know if my usage is proper or not. I would appreciate some insight into this.

Some links

http://lists.w3.org/Archives/Public/ietf-http-wg/2011OctDec/0133.html

Community
  • 1
  • 1
Win Myo Htet
  • 5,377
  • 3
  • 38
  • 56
  • Just curious: What are you sending in the body of your request, using the head for data? – Bergi Mar 20 '12 at 00:33
  • 1
    It is HttpGet.I am not sending anything in the body. – Win Myo Htet Mar 20 '12 at 00:38
  • Encode the entire principle object in to URL-friendly format, put it in querystring. Decode and parse wherever you need to use it. – tu4n Nov 04 '16 at 04:27
  • 2
    If you really need it in header, base64encode the whole JSON string before setHeader – tu4n Nov 04 '16 at 20:20
  • 1
    I think this is an interesting idea. I presume you're passing authentication data in the header. Since authentication data is presumably not related to the purpose/intent of your request but is merely a preamble or a kind of metadata, then I think it fits well in the header. – Aquarelle Apr 26 '17 at 03:46

5 Answers5

44

Yes, you may use JSON in HTTP headers, given some limitations.

According to the HTTP spec, your header field-body may only contain visible ASCII characters, tab, and space.

Since many JSON encoders (e.g. json_encode in PHP) will encode invisible or non-ASCII characters (e.g. "é" becomes "\u00e9"), you often don't need to worry about this.

Check the docs for your particular encoder or test it, though, because JSON strings technically allow most any Unicode character. For example, in JavaScript JSON.stringify() does not escape multibyte Unicode, by default. However, you can easily modify it to do so, e.g.

var charsToEncode = /[\u007f-\uffff]/g;
function http_header_safe_json(v) {
  return JSON.stringify(v).replace(charsToEncode,
    function(c) {
      return '\\u'+('000'+c.charCodeAt(0).toString(16)).slice(-4);
    }
  );
}

Source

Alternatively, you can do as @rocketspacer suggested and base64-encode the JSON before inserting it into the header field (e.g. how JWT does it). This makes the JSON unreadable (by humans) in the header, but ensures that it will conform to the spec.


Worth noting, the original ARPA spec (RFC 822) has a special description of this exact use case, and the spirit of this echoes in later specs such as RFC 7230:

Certain field-bodies of headers may be interpreted according to an internal syntax that some systems may wish to parse.

Also, RFC 822 and RFC 7230 explicitly give no length constraints:

HTTP does not place a predefined limit on the length of each header field or on the length of the header section as a whole, as described in Section 2.5.

jchook
  • 6,690
  • 5
  • 38
  • 40
  • 2
    Can you please tell, is it good practice to send json in the header? What is the difference between these two approaches? When to use which? – Turkhan Badalov Mar 30 '17 at 01:36
17

Base64encode it before sending. Just like how JSON Web Token do it.
Here's a NodeJs Example:

const myJsonStr = JSON.stringify(myData);
const headerFriendlyStr = Buffer.from(myJsonStr, 'utf8').toString('base64');
res.addHeader('foo', headerFriendlyStr);

Decode it when you need reading:

const myBase64Str = req.headers['foo'];
const myJsonStr = Buffer.from(myBase64Str, 'base64').toString('utf8');
const myData = JSON.parse(myJsonStr);
tu4n
  • 4,200
  • 6
  • 36
  • 49
6

Generally speaking you do not send data in the header for a REST API. If you need to send a lot of data it best to use an HTTP POST and send the data in the body of the request. But it looks like you are trying to pass credentials in the header, which some REST API's do use. Here is an example for passing the credentials in a REST API for a service called SMSIfied, which allows you to send SMS text message via the Internet. This example is using basic authentication, which is a a common technique for REST API's. But you will need to use SSL with this technique to make it secure. Here is an example on how to implement basic authentication with WCF and REST.

Kevin Junghans
  • 17,475
  • 4
  • 45
  • 62
  • I have got the authentication part. http://stackoverflow.com/q/9643115/319058 I am more interested in the analysis of my usage of json string in the header – Win Myo Htet Mar 21 '12 at 15:21
  • 1
    @WinMyoHtet Per my answer; do not send data (JSON or XML) in the header. Use POST and put the data in the body of the request. If you have to use GET put the data in the URL query string. When designing a REST API you use GET to read data (i.e. no state change to service) and you use POST to insert or update data. – Kevin Junghans Mar 21 '12 at 19:51
  • I can understand no XML in header since XML is quite bloated but JSON is different. It is light weight. (Thus, it is being proposed in the provided mail thread archive) What I am putting in the header is authorization token to validate the user. I am not making any state changes here. – Win Myo Htet Mar 22 '12 at 00:27
  • The proposal in the referenced thread has not been accepted yet. You said you had the authentication part, but none of the security mechanisms I have seen use clear JSON in the header. For a better discussion on REST security I would look at this post http://stackoverflow.com/questions/7551/best-practices-for-securing-a-rest-api-web-service. It is best to use existing HTTP related security standards such as basic authentication, which uses an encoded string in the header for the credentials and TSL for transport. – Kevin Junghans Mar 22 '12 at 12:50
  • Everything I am doing here is over https. I believe that you already know https encrypt including the headers http://stackoverflow.com/q/187655/319058 – Win Myo Htet Mar 22 '12 at 16:26
  • Sorry I switched the acronym for Transport Security Layer (TLS)to TSL in my previous comment. TLS is analogous to HTTPS and yes I know it is encrypted. Yet the HTTP standard for basic authentication uses an encoded string http://www.ietf.org/rfc/rfc2617.txt. I tend to stick with standards rather than invent my own security schemes. – Kevin Junghans Mar 22 '12 at 18:13
  • HTTP Headers by definition are data. Instead of "generally", headers are best for information that doesn't apply to the business rules of a particular request. One example: custom device information such as device info. This helps keep the HTTP body free of system level concerns. If a concept in a header has multiple data points, it is then maybe worthwhile to pass them as JSON in a single header. You may even use that header data to formulate a response (e.g., selecting image size to return based on screen information in the header - another non request specific concern). – methodsignature Mar 31 '20 at 02:48
5

From what I understand using a json string in the header option is not as much of an abuse of usage as using http DELETE for http GET, thus there has even been proposal to use json in http header. Of course more thorough insights are still welcome and the accepted answer is still to be given.

Win Myo Htet
  • 5,377
  • 3
  • 38
  • 56
2

In the design-first age the OpenAPI specification gives another perspective:

  • an HTTP header parameter may be an object, e.g. object X-MyHeader is

    {"role": "admin", "firstName": "Alex"}

  • however, within the HTTP request/response the value is serialized, e.g.

    X-MyHeader: role=admin,firstName=Alex

KarelHusa
  • 1,995
  • 18
  • 26