NAME
Protocol::HTTP2::Server - HTTP/2 server
SYNOPSIS
# You must create tcp server yourself
use
AnyEvent;
use
AnyEvent::Socket;
use
AnyEvent::Handle;
my
$w
= AnyEvent->condvar;
# Plain-text HTTP/2 connection
tcp_server
'localhost'
, 8000,
sub
{
my
(
$fh
,
$peer_host
,
$peer_port
) =
@_
;
my
$handle
;
$handle
= AnyEvent::Handle->new(
fh
=>
$fh
,
autocork
=> 1,
on_error
=>
sub
{
$_
[0]->destroy;
"connection error\n"
;
},
on_eof
=>
sub
{
$handle
->destroy;
}
);
# Create Protocol::HTTP2::Server object
my
$server
;
$server
= Protocol::HTTP2::Server->new(
on_request
=>
sub
{
my
(
$stream_id
,
$headers
,
$data
) =
@_
;
my
$message
=
"hello, world!"
;
# Response to client
$server
->response(
':status'
=> 200,
stream_id
=>
$stream_id
,
# HTTP/1.1 Headers
headers
=> [
'server'
=>
'perl-Protocol-HTTP2/0.13'
,
'content-length'
=>
length
(
$message
),
'cache-control'
=>
'max-age=3600'
,
'date'
=>
'Fri, 18 Apr 2014 07:27:11 GMT'
,
'last-modified'
=>
'Thu, 27 Feb 2014 10:30:37 GMT'
,
],
# Content
data
=>
$message
,
);
},
);
# First send settings to peer
while
(
my
$frame
=
$server
->next_frame ) {
$handle
->push_write(
$frame
);
}
# Receive clients frames
# Reply to client
$handle
->on_read(
sub
{
my
$handle
=
shift
;
$server
->feed(
$handle
->{rbuf} );
$handle
->{rbuf} =
undef
;
while
(
my
$frame
=
$server
->next_frame ) {
$handle
->push_write(
$frame
);
}
$handle
->push_shutdown
if
$server
->
shutdown
;
}
);
};
$w
->
recv
;
DESCRIPTION
Protocol::HTTP2::Server is HTTP/2 server library. It's intended to make http2-server implementations on top of your favorite event loop.
See also Shuvgey - AnyEvent HTTP/2 Server for PSGI based on Protocol::HTTP2::Server.
METHODS
new
Initialize new server object
my
$server
= Protocol::HTTP2::Client->new(
%options
);
Available options:
- on_request => sub {...}
-
Callback invoked when receiving client's requests
on_request
=>
sub
{
# Stream ID, headers array reference and body of request
my
(
$stream_id
,
$headers
,
$data
) =
@_
;
my
$message
=
"hello, world!"
;
$server
->response(
':status'
=> 200,
stream_id
=>
$stream_id
,
headers
=> [
'server'
=>
'perl-Protocol-HTTP2/0.13'
,
'content-length'
=>
length
(
$message
),
],
data
=>
$message
,
);
...
},
- upgrade => 0|1
-
Use HTTP/1.1 Upgrade to upgrade protocol from HTTP/1.1 to HTTP/2. Upgrade possible only on plain (non-tls) connection.
- on_error => sub {...}
-
Callback invoked on protocol errors
on_error
=>
sub
{
my
$error
=
shift
;
...
},
- on_change_state => sub {...}
-
Callback invoked every time when http/2 streams change their state. See Stream States
on_change_state
=>
sub
{
my
(
$stream_id
,
$previous_state
,
$current_state
) =
@_
;
...
},
response
Prepare response
my
$message
=
"hello, world!"
;
$server
->response(
# HTTP/2 status
':status'
=> 200,
# Stream ID
stream_id
=>
$stream_id
,
# HTTP/1.1 headers
headers
=> [
'server'
=>
'perl-Protocol-HTTP2/0.01'
,
'content-length'
=>
length
(
$message
),
],
# Body of response
data
=>
$message
,
);
response_stream
If body of response is not yet ready or server will stream data
# P::H::Server::Stream object
my
$server_stream
;
$server_stream
=
$server
->response_stream(
# HTTP/2 status
':status'
=> 200,
# Stream ID
stream_id
=>
$stream_id
,
# HTTP/1.1 headers
headers
=> [
'server'
=>
'perl-Protocol-HTTP2/0.01'
,
],
# Callback if client abort this stream
on_cancel
=>
sub
{
...
}
);
# Send partial data
$server_stream
->
send
(
$chunk_of_data
);
$server_stream
->
send
(
$chunk_of_data
);
## 3 ways to finish stream:
#
# The best: send last chunk and close stream in one action
$server_stream
->
last
(
$chunk_of_data
);
# Close the stream (will send empty frame)
$server_stream
->
close
();
# Destroy object (will send empty frame)
undef
$server_stream
push
Prepare Push Promise. See Server Push
# Example of push inside of on_request callback
on_request
=>
sub
{
my
(
$stream_id
,
$headers
,
$data
) =
@_
;
my
%h
= (
@$headers
);
# Push promise (must be before response)
if
(
$h
{
':path'
} eq
'/index.html'
) {
# index.html contain styles.css resource, so server can push
# "/style.css" to client before it request it to increase speed
# of loading of whole page
$server
->
push
(
':authority'
=>
'localhost:8000'
,
':method'
=>
'GET'
,
':path'
=>
'/style.css'
,
':scheme'
=>
'http'
,
stream_id
=>
$stream_id
,
);
}
$server
->response(...);
...
}
shutdown
Get connection status:
next_frame
get next frame to send over connection to client. Returns:
# Example
while
(
my
$frame
=
$server
->next_frame ) {
syswrite
$fh
,
$frame
;
}
feed
Feed decoder with chunks of client's request
sysread
$fh
,
$binary_data
, 4096;
$server
->feed(
$binary_data
);
ping
Send ping frame to client (to keep connection alive)
$server
->ping
or
$server
->ping(
$payload
);
Payload can be arbitrary binary string and must contain 8 octets. If payload argument is omitted server will send random data.