unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "Jarosław Rzeszótko" <sztywny@gmail.com>
To: 16220@debbugs.gnu.org
Subject: bug#16220: url-http.el: Not conforming to HTTP spec
Date: Sun, 22 Dec 2013 21:52:22 +0100	[thread overview]
Message-ID: <CAHnYAZb+uWpfVM_KLjNcN1cV2vKv=p4qHjvgQZqriWDAT8WiFQ@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 3411 bytes --]

Hi,

At the end of every HTTP request to be made with url-http.el and containing
a body, an unnecessary "\r\n" is appended, and additionally those two
characters are not used in the calculation of the Content-Length header.
This normally would not matter, because a carefully build server will
anyway only read "Content-Length" bytes from the body and ignore the final
CRLF, but Emacs additionally defaults to using Connection: keep-alive,
which results in the TCP traffic for what was meant to be a single request,
being interpreted as two separate HTTP requests, the first one being
roughly the intended one, and the other one consisting only of CRLF. In
particular, I am using the HTTP server from net.http in Go language. That
keepalive is enabled by default is strange, especially given how the
variable that controls this is described:

(defvar url-http-attempt-keepalives t
  "Whether to use a single TCP connection multiple times in HTTP.
This is only useful when debugging the HTTP subsystem.  Setting to
nil will explicitly close the connection to the server after every
request.")

Those issues have been somewhat discussed here, but it seems the people
discussing unfortunately don't understand HTTP:

https://groups.google.com/forum/#!msg/gnu.emacs.bug/SF4P7gVI6IQ/SExtWzutKI4J

Please just compare this discussion to
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html

If you don't go into any fancy things like chunked encoding etc., an HTTP
request is a:

- sequence of headers, each header followed with a newline
- a newline terminating the sequence of headers
- an optional request body

The request body will be read by the server only if one of the headers is a
Content-Length header, and the value of the header is exactly the number of
bytes that is being sent, there is no CRLF terminating the body.  So if
there is no body, the request ends with two CRLFs, if there is a body, it
just ends with [Content-Length] bytes of raw data. There is no possibility
a proper HTTP server could be confused by a request being terminated with
two CRLFs, if the request is otherwise correct. I think there must have
been some confusion as to the reason of the original problem, that was then
turned into this "fix".

For reference, my code is roughly this, and as mentioned I am using
net.http from the Go language on the other end:

(defun server-command (command)
  (let* ((url-request-method "POST")
         (url-request-extra-headers '(("Content-Type" .
"application/x-www-form-urlencoded")))
         (url-request-data (concat (url-hexify-string "command") "="
(url-hexify-string (json-encode command))))
         (result-buffer (url-retrieve-synchronously server-url))
         (result
          (with-current-buffer result-buffer
            (goto-char (point-min))
            (delete-region (point-min) (search-forward "\n\n"))
            (buffer-string))))
    (kill-buffer result-buffer)
    result))

Normally I get from this function the contents of the first, "correct"
response body from the server, but if I run it a few times in quick
succession I additonally get the string "HTTP/1.1 400 Bad Request" at the
end, which is actually the second HTTP response showing up at random in the
buffer (altough it's consistently sent by the server every time, as I can
see in a sniffer).

Cheers,
Jarosław Rzeszótko

[-- Attachment #2: Type: text/html, Size: 3893 bytes --]

             reply	other threads:[~2013-12-22 20:52 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-22 20:52 Jarosław Rzeszótko [this message]
2013-12-22 21:55 ` bug#16220: url-http.el: Not conforming to HTTP spec Jarosław Rzeszótko
2013-12-22 22:33   ` Ted Zlatanov
2013-12-23  6:51     ` Jarosław Rzeszótko
2013-12-23 13:08       ` Ted Zlatanov
2013-12-24  7:50   ` Lars Ingebrigtsen
2013-12-24  8:28     ` Jarosław Rzeszótko
2013-12-24 14:43 ` Stefan Monnier
2013-12-24 16:31   ` Jarosław Rzeszótko
2014-01-02  2:21     ` Stefan Monnier
2014-01-03 18:06       ` Jarosław Rzeszótko
2014-01-05  9:57       ` Lars Magne Ingebrigtsen
2014-01-05 13:25         ` Jarosław Rzeszótko
2014-01-06 15:06         ` Stefan Monnier
2014-01-07 19:30           ` Jarosław Rzeszótko
2014-01-08 18:29             ` Stefan Monnier
2014-01-18 22:35 ` Paul Eggert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAHnYAZb+uWpfVM_KLjNcN1cV2vKv=p4qHjvgQZqriWDAT8WiFQ@mail.gmail.com' \
    --to=sztywny@gmail.com \
    --cc=16220@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).