-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Some extra documentation and a go-node interop example #5
base: master
Are you sure you want to change the base?
Changes from 4 commits
b167ce6
73af706
6e56de3
2cbef27
b0e4d5e
407d5ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
node_modules/ | ||
npm-debug.log | ||
.vimrc |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,23 +10,32 @@ SPDY/HTTP2 generic transport implementation. | |
|
||
## Usage | ||
|
||
### server | ||
|
||
```javascript | ||
var transport = require('spdy-transport'); | ||
|
||
// NOTE: socket is some stream or net.Socket instance, may be an argument | ||
// of `net.createServer`'s connection handler. | ||
|
||
var server = transport.connection.create(socket, { | ||
protocol: 'http2', | ||
protocol: 'http2', // or 'spdy' | ||
isServer: true | ||
}); | ||
|
||
server.on('stream', function(stream) { | ||
console.log(stream.method, stream.path, stream.headers); | ||
|
||
// necessary for the stream to be established in both ends | ||
stream.respond(200, { | ||
header: 'value' | ||
}); | ||
|
||
// response body | ||
stream.write(<data>) | ||
|
||
stream.end() // sends FLAG_FIN, setting the connection half open | ||
|
||
stream.on('readable', function() { | ||
var chunk = stream.read(); | ||
if (!chunk) | ||
|
@@ -44,6 +53,75 @@ server.on('stream', function(stream) { | |
}); | ||
``` | ||
|
||
### client | ||
|
||
```javascript | ||
var transport = require('spdy-transport') | ||
|
||
// NOTE: socket is some stream or net.Socket instance, may be an argument | ||
// of `net.createServer`'s connection handler. | ||
|
||
var client = transport.connection.create(socket, { | ||
protocol: 'http2', | ||
isServer: false | ||
}) | ||
|
||
// optional for http2, however mandatory for spdy ([2, 3, 3.1]) | ||
client.start(4) | ||
|
||
client.request({ | ||
method: 'GET', | ||
host: 'localhost', | ||
path: '/', | ||
headers: { | ||
a: 'b', | ||
c: 'd' | ||
} | ||
}, function (err, stream) { | ||
if (err) { | ||
return console.log(err) | ||
} | ||
|
||
stream.on('response', function (code, headers) { | ||
console.log(code, headers) | ||
|
||
// request body | ||
stream.write(<data>) | ||
|
||
// And other node.js Stream APIs | ||
// ... | ||
}) | ||
|
||
stream.on('readable', function () { | ||
var chunk = stream.read() | ||
if (!chunk) { | ||
return | ||
} | ||
console.log(chunk.toString()) | ||
}) | ||
}) | ||
``` | ||
|
||
### frame listener | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is kind of internal thing, just for testing. Are you sure that it is worth putting it into readme? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting, so how should we correctly read the body sent by the server? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it. Although I believe it might be a nice reminder that a good way to check if more bytes are available is through the .on('readable') event. Have seen a couple of times folks doing something like:
What if I left only the stream.read() and a comment with a note about the .on('readable') event? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm... I'm not sure if this library is the right place to educate people on how the streams2 API should be used. I'd just link the node documentation if you think that this question is going to be raised often. |
||
|
||
```javascript | ||
// either client or server | ||
connection.on('frame', function (frame) { | ||
console.log(frame.type) | ||
}) | ||
``` | ||
|
||
## Implementation notes | ||
|
||
- spdy-transport always sends a SETTINGS frame as the first frame once the socket is open | ||
- the server requires a http `":method"` and `":path"` header. If they are not added on the client, `"GET"` and `"/"` are added by default | ||
|
||
## Interop | ||
|
||
`spdy-transport` is capable of interoping with other spdy framing layer implementations such as: | ||
|
||
- [spdystream](https://github.com/docker/spdystream), [example](/examples/spdystream-interop) | ||
|
||
## LICENSE | ||
|
||
This software is licensed under the MIT License. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"github.com/docker/spdystream" | ||
"net" | ||
"net/http" | ||
) | ||
|
||
func main() { | ||
conn, err := net.Dial("tcp", "localhost:9090") | ||
if err != nil { | ||
panic(err) | ||
} | ||
spdyConn, err := spdystream.NewConnection(conn, false) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
header := http.Header{} | ||
// Although spdystream doesn't mind about :method and :path headers, these | ||
// are necessary for interop with spdy-transport | ||
header.Add(":method", "GET") | ||
header.Add(":path", "/") | ||
|
||
go spdyConn.Serve(spdystream.NoOpStreamHandler) | ||
|
||
stream, err := spdyConn.CreateStream(header, nil, false) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
stream.Wait() | ||
|
||
fmt.Fprint(stream, "Hey, how is it going! (go client asking)") | ||
|
||
buf := make([]byte, 35) | ||
stream.Read(buf) | ||
fmt.Println(string(buf)) | ||
|
||
stream.Close() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
var tcp = require('net') | ||
var transport = require('spdy-transport') | ||
|
||
var socket = tcp.connect({port: 9090}, function () { | ||
|
||
var client = transport.connection.create(socket, { | ||
protocol: 'spdy', | ||
isServer: false | ||
}) | ||
|
||
client.on('frame', function (frame) { | ||
console.log(frame.type) | ||
}) | ||
|
||
client.start(3.1) | ||
|
||
client.request({ | ||
method: 'GET', | ||
host: 'localhost', | ||
path: '/', | ||
headers: { | ||
a: 'b' | ||
}}, function (err, stream) { | ||
console.log('stream established') | ||
if (err) { | ||
return console.log(err) | ||
} | ||
stream.write('Hey, how is it going. (node client asking)!') | ||
|
||
stream.on('readable', function () { | ||
var chunk = stream.read() | ||
if (!chunk) { | ||
return | ||
} | ||
console.log(chunk.toString()) | ||
}) | ||
|
||
stream.on('response', function (code, headers) { | ||
console.log(code, headers) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/docker/spdystream" | ||
"net" | ||
) | ||
|
||
func main() { | ||
listener, err := net.Listen("tcp", "localhost:9090") | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
for { | ||
conn, err := listener.Accept() | ||
if err != nil { | ||
panic(err) | ||
} | ||
spdyConn, err := spdystream.NewConnection(conn, true) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// This is an "echo server" example, known in the go world as "mirror" | ||
go spdyConn.Serve(spdystream.MirrorStreamHandler) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
var tcp = require('net') | ||
var transport = require('spdy-transport') | ||
|
||
tcp.createServer(function (socket) { | ||
var server = transport.connection.create(socket, { | ||
protocol: 'spdy', | ||
isServer: true | ||
}) | ||
|
||
server.on('stream', function (stream) { | ||
console.log(stream.method, stream.path, stream.headers) | ||
|
||
stream.respond(200, { | ||
c: 'd' | ||
}) | ||
stream.write('Hey, how is it going? (node server asking') | ||
|
||
stream.on('readable', function () { | ||
var chunk = stream.read() | ||
if (!chunk) { | ||
return | ||
} | ||
console.log(chunk.toString()) | ||
}) | ||
|
||
stream.on('end', function () { | ||
console.log('end') | ||
}) | ||
}) | ||
|
||
}).listen(9090) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that it is actually that optional. ;)