Closed felicienfrancois closed 7 years ago
I'm not so sure - there's no better way to get someone to fix their code than by throwing a breaking exception! Regardless, if we do go the route of not throwing an exception, we should in no case set a deprecated header - there are other endpoints that will get mad at us if we send one.
Also, what header (specifically) are you setting that causes the exception? There is, perhaps, a better alternative that can/should be used in all cases.
I get this error on the following headers:
host
on requeststransfer-encoding
and connection
on responsesHere more arguments in favor of not breaking:
error
event so it can be handled, not to throw an exceptionAlso, as far as I understood, http2 is not only an HTTP/2 server but an HTTP server that supports HTTP/2. http2 also handles HTTP 1.1 request/response, transparently, using the same event handlers right ? If so, HTTP 1.1 headers deprecated in HTTP/2 should not be breaking in http2 which have to handle both protocols transparently.
Also, When I write this
http2.request({
hostname: 'myhost.com',
port: 443,
path: '/',
method: 'GET',
headers: {
'Some-Deprecated-Header': 'SomeValue'
}
}, function(response) {
});
How can you know if the request will be HTTP/2 or HTTP 1.1 before connecting to the server?
I am using http-proxy in development environment(with gulp-connect) as reverse proxy for the api-server. This behavior will break the connection, because http-proxy auto add connection
to the request, and it can't override in client-side code.
I agree there at least an option to let user code to configure this behavior, handle both protocols transparently.
I got here trying to use weinre. I didn't debug the problem fully - but I haven't had this issue until just now trying to hook weinre up.
It's an old project, I wouldn't expect it to update deprecated headers. It's also an extremely useful tool however and this behavior is preventing me from using it.
I do appreciate the http2 project though. It's been awesome to me :)
I am investigating this right now as I have encountered a site that uses Host
headers with their push promises. I think throwing is not the right behavior.
I found the following comment in node-http2
’s the code:
// * An HTTP/2.0 request or response MUST NOT include any of the following header fields:
// Connection, Host, Keep-Alive, Proxy-Connection, Transfer-Encoding, and Upgrade. A server
// MUST treat the presence of any of these header fields as a stream error of type
// PROTOCOL_ERROR.
Looking at the HTTP/2 spec, the wording is different:
Clients that generate HTTP/2 requests directly SHOULD use the :authority
pseudo-header field instead of the Host header field.
A little further up in the spec:
This means that an intermediary transforming an HTTP/1.x message to HTTP/2
will need to remove any header fields nominated by the Connection header field,
along with the Connection header field itself. Such intermediaries **SHOULD** also
remove other connection-specific header fields, such as Keep-Alive, Proxy-Connection,
Transfer-Encoding, and Upgrade, even if they are not nominated by the Connection header field.
This obviously only loosely applies to node-http2
, but I think it shows that the spec intends for clients to not break if these headers get sent. Therefore, I think it would be good for node-http2
to not break on deprecated headers but issue a warn-level log instead.
I’ll gladly open a PR for this if the maintainer agree that this is an acceptable approach.
Thanks a ton for mentioning the comment vs spec language. Interesting because specs don't change once published, but the comment reads as if it were copy/pasted.
@nwgh
I'm not so sure - there's no better way to get someone to fix their code than by throwing a breaking exception!
I disagree, because someone
might be a 3rd party HTTP/1 server, for example, CouchDB, which uses only HTTP/1. You're forgetting that node-http2
can and will be used as a proxy and for now mostly as HTTP/2 to HTTP/1. This should be focused around actual usage and not "programming best practices". You can add strict mode for those who want to be as close to spec as possible.
@pavel If I understand it right I currently have exactly this scenario. I'm using BrowserSync to proxy our application server and serve static frontend resources. There would be a lot to do on the application server to migrate to HTTP/1 and I only would like to use http2 for serving the mass of small JS modules through SystemJS a bit faster, so I could speed up frontend development. But this error doesn't allow me to use http2 module in browsersync.
@DaSchTour You can use node-spdy instead as it does handle such cases. (I assume that the reader understands that this advice is not advertisement of node-spdy, and just a library to workaround the issue. No comparison should be implied from my comment).
BrowserSync usage example:
// First run: npm install browser-sync spdy
const bs = require('browser-sync').create();
bs.init({
server: './app',
httpModule: 'spdy',
https: true
});
@pavel thanks for the workaround. Since SPDY is some kind of subset of HTTP2 this is a fair suggestion. In the longterm we all will migrate to HTTP2 as this is the new standard. But It's a long road to go. So luckily there are some "bridge" technologies :D Sadly Chrome already removed support for SPDY 😞
@DaSchTour Actually node-spdy
provides HTTP/2 support. Though the name mentions spdy
HTTP/2 support is provided as well. From node-spdy
github page:
With this module you can create HTTP2 / SPDY servers in node.js with natural http module interface and fallback to regular https (for browsers that don't support neither HTTP2, nor SPDY yet).
@pavel completely agree, this has nothing to do with broken code. Some services just use different protocols, and to say that a service that isn't using HTTP2 is broken is pretty bold.
This will not be fixed. node-http2 only speaks http/2, and if something is speaking http/2 and sending a deprecated header, that something is broken.
The current behavior prevent from simply replacing
https
byhttp2
in existing peace of softwareIt should not throw a breaking exception. Instead It should:
But in all cases, the request should be processed