This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Merge branch 'http_agent'

  • Loading branch information...
2 parents ae30af4 + a867476 commit 6eca6b1ec05c5b386121a992dc7f6502f001f052 @ry ry committed Jan 21, 2011
View
@@ -22,7 +22,6 @@ HTTP API is very low-level. It deals with stream handling and message
parsing only. It parses a message into headers and body but it does not
parse the actual headers or the body.
-HTTPS is supported if OpenSSL is available on the underlying platform.
## http.Server
@@ -311,34 +310,57 @@ If `data` is specified, it is equivalent to calling `response.write(data, encodi
followed by `response.end()`.
-## http.Client
+## http.request(options, callback)
-An HTTP client is constructed with a server address as its
-argument, the returned handle is then used to issue one or more
-requests. Depending on the server connected to, the client might
-pipeline the requests or reestablish the stream after each
-stream. _Currently the implementation does not pipeline requests._
+Node maintains several connections per server to make HTTP requests.
+This function allows one to transparently issue requests.
-Example of connecting to `google.com`:
+Options:
- var http = require('http');
- var google = http.createClient(80, 'www.google.com');
- var request = google.request('GET', '/',
- {'host': 'www.google.com'});
- request.end();
- request.on('response', function (response) {
- console.log('STATUS: ' + response.statusCode);
- console.log('HEADERS: ' + JSON.stringify(response.headers));
- response.setEncoding('utf8');
- response.on('data', function (chunk) {
+- `host`: A domain name or IP address of the server to issue the request to.
+- `port`: Port of remote server.
+- `method`: A string specifing the HTTP request method. Possible values:
+ `'GET'` (default), `'POST'`, `'PUT'`, and `'DELETE'`.
@tj

tj Jan 21, 2011

HEAD, OPTIONS, etc?

@TooTallNate

TooTallNate Jan 21, 2011

iirc the client actually doesn't care about which method is passed. you can send any arbitrary String as the method. This is not the case for the http.Server however...

@tj

tj Jan 21, 2011

of course, but it's a bit misleading for new people to list "possible values" and only name those 4 :p

+- `path`: Request path. Should include query string and fragments if any.
+ E.G. `'/index.html?page=12'`
+- `headers`: An object containing request headers.
+
+`http.request()` returns an instance of the `http.ClientRequest`
+class. The `ClientRequest` instance is a writable stream. If one needs to
+upload a file with a POST request, then write to the `ClientRequest` object.
+
+Example:
+
+ var options = {
+ host: 'www.google.com',
+ port: 80,
+ path: '/upload',
+ method: 'POST'
+ };
+
+ var req = http.request(options, function(res) {
+ console.log('STATUS: ' + res.statusCode);
+ console.log('HEADERS: ' + JSON.stringify(res.headers));
+ res.setEncoding('utf8');
+ res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
-There are a few special headers that should be noted.
+ // write data to request body
+ req.write('data\n');
+ req.write('data\n');
+ req.end();
+
+Note that in the example `req.end()` was called. With `http.request()` one
+must always call `req.end()` to signify that you're done with the request -
+even if there is no data being written to the request body.
-* The 'Host' header is not added by Node, and is usually required by
- website.
+If any error is encountered during the request (be that with DNS resolution,
+TCP level errors, or actual HTTP parse errors) an `'error'` event is emitted
+on the returned request object.
+
+There are a few special headers that should be noted.
* Sending a 'Connection: keep-alive' will notify Node that the connection to
the server should be persisted until the next request.
@@ -350,6 +372,33 @@ There are a few special headers that should be noted.
and listen for the `continue` event. See RFC2616 Section 8.2.3 for more
information.
+## http.get(options, callback)
+
+Since most requests are GET requests without bodies, Node provides this
+convience method. The only difference between this method and `http.request()` is
+that it sets the method to GET and calls `req.end()` automatically.
+
+Example:
+
+ var options = {
+ host: 'www.google.com',
+ port: 80,
+ path: '/index.html'
+ };
+
+ http.get(options, function(res) {
+ console.log("Got response: " + res.statusCode);
+ }).on('error', function(e) {
+ console.log("Got error: " + e.message);
+ });
+
+
+## http.Agent
+
+`http.request()` uses a special `Agent` for managing multiple connections to
+an HTTP server. Normally `Agent` instances should not be exposed to user
+code, however in certain situations it's useful to check the status of the
+agent.
### Event: 'upgrade'
@@ -369,56 +418,24 @@ Emitted when the server sends a '100 Continue' HTTP response, usually because
the request contained 'Expect: 100-continue'. This is an instruction that
the client should send the request body.
+### agent.maxSockets
-### http.createClient(port, host='localhost', secure=false, [credentials])
-
-Constructs a new HTTP client. `port` and
-`host` refer to the server to be connected to. A
-stream is not established until a request is issued.
-
-`secure` is an optional boolean flag to enable https support and `credentials` is an optional
-credentials object from the crypto module, which may hold the client's private key,
-certificate, and a list of trusted CA certificates.
-
-If the connection is secure, but no explicit CA certificates are passed
-in the credentials, then node.js will default to the publicly trusted list
-of CA certificates, as given in <http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt>.
+By default set to 5. Determines how many concurrent sockets the agent can have open.
-### client.request(method='GET', path, [request_headers])
+### agent.sockets
-Issues a request; if necessary establishes stream. Returns a `http.ClientRequest` instance.
+An array of sockets currently inuse by the Agent. Do not modify.
-`method` is optional and defaults to 'GET' if omitted.
+### agent.queue
-`request_headers` is optional.
-Additional request headers might be added internally
-by Node. Returns a `ClientRequest` object.
+A queue of requests waiting to be sent to sockets.
-Do remember to include the `Content-Length` header if you
-plan on sending a body. If you plan on streaming the body, perhaps
-set `Transfer-Encoding: chunked`.
-
-*NOTE*: the request is not complete. This method only sends the header of
-the request. One needs to call `request.end()` to finalize the request and
-retrieve the response. (This sounds convoluted but it provides a chance for
-the user to stream a body to the server with `request.write()`.)
-
-### client.verifyPeer()
-
-Returns true or false depending on the validity of the server's certificate
-in the context of the defined or default list of trusted CA certificates.
-
-### client.getPeerCertificate()
-
-Returns a JSON structure detailing the server's certificate, containing a dictionary
-with keys for the certificate `'subject'`, `'issuer'`, `'valid_from'` and `'valid_to'`.
## http.ClientRequest
-This object is created internally and returned from the `request()` method
-of a `http.Client`. It represents an _in-progress_ request whose header has
-already been sent.
+This object is created internally and returned from `http.request()`. It
+represents an _in-progress_ request whose header has already been sent.
To get the response, add a listener for `'response'` to the request object.
`'response'` will be emitted from the request object when the response
@@ -488,7 +505,7 @@ followed by `request.end()`.
## http.ClientResponse
-This object is created when making a request with `http.Client`. It is
+This object is created when making a request with `http.request()`. It is
passed to the `'response'` event of the request object.
The response implements the `Readable Stream` interface.
@@ -499,10 +516,6 @@ The response implements the `Readable Stream` interface.
Emitted when a piece of the message body is received.
- Example: A chunk of the body is given as the single
- argument. The transfer-encoding has been decoded. The
- body chunk a String. The body encoding is set with
- `response.setBodyEncoding()`.
### Event: 'end'
@@ -542,7 +555,3 @@ Pauses response from emitting events. Useful to throttle back a download.
### response.resume()
Resumes a paused response.
-
-### response.client
-
-A reference to the `http.Client` that this response belongs to.
Oops, something went wrong.

11 comments on commit 6eca6b1

This is awesome.

tj replied Jan 21, 2011

looking good

tj replied Jan 21, 2011

could we have an option to follow redirects? or is stuff like that out of scope for core?

I would like it to say pretty low level. But it should be easy to bolt things on top like follow redirects, retrys, etc. What if you could pass state commands back? You check the status code in the callback and you can pass commands back in via return.

https://gist.github.com/789962

I realize this is a pretty big departure from the current conventions. I think it's cool though.

tj replied Jan 21, 2011

if you were to do that it misewell be a callback, so you could say do some async check, decide ok I want to follow this, go ahead. I dunno yeah maybe it is to high level

ry replied Jan 21, 2011

polotek, i like your idea.

tj replied Jan 21, 2011

I dig it too, how about a callback instead (although slightly more costly I suppose), so that we can do async stuff before deciding on the state

I agree we should be able to do async first. But that could get tricky. With the return, you know you're communicating back to the request engine in the state right after the last response. That should make it easier to tell it to redirect, follow, etc because it still has everything it needs to do that. After yeilding back to the event loop, who knows.

The only thing that occurs to me right now is making it a function of the request. I'm not sure if I like it, but check it out.

https://gist.github.com/789962

tj replied Jan 21, 2011

I would do something this https://gist.github.com/790207

+1 to passing the request to callback. Other than that there's not much difference. I'm not particular about what form the commands take.

tj replied Jan 21, 2011

strings are cheap and simple. it would be nice (to high level?) to have some of the methods for classifying the response statusCode, res.isError == res.isClientError || res.isServerError etc

Please sign in to comment.