Fetch: Why should we do toLowerCase to header name (by normalizeName()) ?

Created on 18 Dec 2015  路  16Comments  路  Source: github/fetch

Code first:

fetch( url, {
    headers:{
        'Cookie':'some key-value pass to server',
        'User-Agent': 'react-native Android'
    }
);

I found that the name of headers has been converted to lower case by normalizeName .

And when I use it on React-Native (Android platform) , it send a HTTP request with lower case header name which not be recognized in our Server.

There is the row HTTP text I've capture:

GET http://... HTTP/1.1
cookie: ...
user-agent: react-native Android 

So. Why should we do toLowerCase to header name ?

Most helpful comment

While Http headers should be case-insensitive, a server for a client we're dealing with has miss implemented the spec. They check authorization header using equality it seems and accordingly produce an error.

We do not have control over modifying the code of that server, we can submit a request but that will take time to process.

If according to the spec the header should be case-insensitive I don't see why forcing the headers to be lower case matters then, we should be generally allowed to send headers in any case form.

All 16 comments

HTTP headers are case insensitive. The lowercase header names were added in #85.

@dgraham. Thx for explanation!

I believe the native fetch implementation (in Chrome/Mac 51.0.2704.84 (64-bit) for me) also downcases the header names.

While Http headers should be case-insensitive, a server for a client we're dealing with has miss implemented the spec. They check authorization header using equality it seems and accordingly produce an error.

We do not have control over modifying the code of that server, we can submit a request but that will take time to process.

If according to the spec the header should be case-insensitive I don't see why forcing the headers to be lower case matters then, we should be generally allowed to send headers in any case form.

chrome-dev-tool Network panel will divide these requests into Other not XHR.

/// request headers
accept:application/json
Accept-Encoding:gzip, deflate
Accept-Language:en,zh;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4,ko;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Length:48
content-type:application/json

So, no way to prevent Lowercasing of headers?

@kobvel That's correct.

chrome-dev-tool Network panel will divide these requests into Other not XHR.

@hashplus you should report that bug to the chrome team.

Same issue when sending requests to Gerrit server

It doesn't work when header 'X-Gerrit-Auth' is transformed to 'x-gerrit-auth' by the fetch API

I can post an issue to the Gerrit team but...
I'm pretty sure that plenty of legacy servers will have similar issues
(even more on custom header names that are not managed by core http server code but by application level one)

Same issue when sending requests to Gerrit server

It doesn't work when header 'X-Gerrit-Auth' is transformed to 'x-gerrit-auth' by the fetch API

I can post an issue to the Gerrit team but...
I'm pretty sure that plenty of legacy servers will have similar issues
(even more on custom header names that are not managed by core http server code but by application level one)

To get an idea, I looked into Gerrit Server implementation

It is based on Tomcat which getHeader() API is case insensitive

This header is occasionally added to the CORS Access-Control-Request-Headers HTTP header.
To handle CORS, they use a filter written this way .filter(h -> !ALLOWED_CORS_REQUEST_HEADERS.contains(h)) and of course, they didn't lowercased their header values before.

I created a ticket to the gerrit project: https://bugs.chromium.org/p/gerrit/issues/detail?id=5733

My point is just that we can be sure that the fetch API is probably unfortunately not usable, as is, on many (how many?) legacy servers.

It may be ok on Open Source project based services, as the mentioned one, to which we can contribute, but it can be a way harder issue when connecting to commercial closed-source services (or open source based ones that are not regularly maintained)

@AMorgaut the workaround I resorted to was using axios until the server I was working with fixed their problem.

since it's fetch that lower cases not the XHR Object

@AMorgaut the workaround I resorted to was using axios until the server I was working with fixed their problem.

since it's fetch that lower cases not the XHR Object

It's not working now! Even the headers in axios are converted to lowercase now.

omg i want to use header as case sensitive any help . i have use and flutter but same as react native . just java is perfect.

This working in react-native, I share here to help anybody.
polyfill.ts

 // Disable lowercase in FormData
//@ts-ignore
FormData.prototype.getParts = function(): Array<FormDataPart> {
  //@ts-ignore
  return this._parts.map(([name, value]) => {
    const contentDisposition = 'form-data; name="' + name + '"';
    //@ts-ignore
    const headers: Headers = { 'Content-Disposition': contentDisposition };

    // The body part is a "blob", which in React Native just means
    // an object with a `uri` attribute. Optionally, it can also
    // have a `name` and `type` attribute to specify filename and
    // content type (cf. web Blob interface.)
    if (typeof value === 'object' && value) {
      if (typeof value.name === 'string') {
        //@ts-ignore
        headers['Content-Disposition'] += '; filename="' + value.name + '"';
      }
      if (typeof value.type === 'string') {
        //@ts-ignore
        headers['Content-Type'] = value.type;
      }
      return { ...value, headers, fieldName: name };
    }
    // Convert non-object values to strings as per FormData.append() spec
    return { string: String(value), headers, fieldName: name };
  });
};

// Disable lowercase in headers
XMLHttpRequest.prototype.setRequestHeader = function(
  header: string,
  value: any
): void {
  if (this.readyState !== this.OPENED) {
    throw new Error('Request has not been opened');
  }
  //@ts-ignore
  this._headers[header /* .toLowerCase() */] = String(value);
};

index.js

import './polyfill.ts'
...

Scripts for Artificial Intelligence

We need Artificial Intelligence since Natural Intelligence is in such short supply!

Was this page helpful?
0 / 5 - 0 ratings