Hypersonic
view release on metacpan or search on metacpan
lib/Hypersonic/Protocol/HTTP2.pm view on Meta::CPAN
->line(' char cl_buf[16];')
->line(' snprintf(cl_buf, sizeof(cl_buf), "%d", body_len);')
->line(' ')
->line(' /* Build status string */')
->line(' char status_buf[4];')
->line(' snprintf(status_buf, sizeof(status_buf), "%d", status);')
->line(' ')
->line(' /* Submit HTTP/2 response headers */')
->line(' nghttp2_nv hdrs[] = {')
->line(' { (uint8_t*)":status", (uint8_t*)status_buf, 7, strlen(status_buf), NGHTTP2_NV_FLAG_NONE },')
->line(' { (uint8_t*)"content-type", (uint8_t*)ct, 12, strlen(ct), NGHTTP2_NV_FLAG_NONE },')
->line(' { (uint8_t*)"content-length", (uint8_t*)cl_buf, 14, strlen(cl_buf), NGHTTP2_NV_FLAG_NONE },')
->line(' };')
->line(' ')
->line(' /* Create data provider for body */')
->line(' nghttp2_data_provider data_prd;')
->line(' data_prd.source.ptr = (void*)body;')
->line(' data_prd.read_callback = h2_data_source_read_cb;')
->line(' ')
->line(' nghttp2_submit_response(session, stream_id, hdrs, 3, &data_prd);')
->line(' nghttp2_session_send(session);')
lib/Hypersonic/Protocol/HTTP2.pm view on Meta::CPAN
# Generate 404 response for HTTP/2
sub gen_404_response {
my ($class, $builder) = @_;
$builder->comment('HTTP/2: Send 404 response')
->line('static void h2_send_404(nghttp2_session* session, int32_t stream_id) {')
->line(' static const char* body = "Not Found";')
->line(' ')
->line(' nghttp2_nv hdrs[] = {')
->line(' { (uint8_t*)":status", (uint8_t*)"404", 7, 3, NGHTTP2_NV_FLAG_NONE },')
->line(' { (uint8_t*)"content-type", (uint8_t*)"text/plain", 12, 10, NGHTTP2_NV_FLAG_NONE },')
->line(' { (uint8_t*)"content-length", (uint8_t*)"9", 14, 1, NGHTTP2_NV_FLAG_NONE },')
->line(' };')
->line(' ')
->line(' nghttp2_data_provider data_prd;')
->line(' data_prd.source.ptr = (void*)body;')
->line(' data_prd.read_callback = h2_data_source_read_cb;')
->line(' ')
->line(' nghttp2_submit_response(session, stream_id, hdrs, 3, &data_prd);')
->line(' nghttp2_session_send(session);')
->line('}')
lib/Hypersonic/Protocol/HTTP2.pm view on Meta::CPAN
my ($class, $builder) = @_;
$builder->comment('HTTP/2 Streaming: Send HEADERS without END_STREAM (allows more DATA)')
->line('static int h2_stream_headers(nghttp2_session* session, int32_t stream_id,')
->line(' int status, const char* content_type) {')
->line(' char status_str[4];')
->line(' snprintf(status_str, sizeof(status_str), "%d", status);')
->line(' ')
->line(' nghttp2_nv hdrs[] = {')
->line(' { (uint8_t*)":status", (uint8_t*)status_str, 7, strlen(status_str), NGHTTP2_NV_FLAG_NONE },')
->line(' { (uint8_t*)"content-type", (uint8_t*)content_type, 12, strlen(content_type), NGHTTP2_NV_FLAG_NONE },')
->line(' };')
->line(' ')
->line(' /* Submit headers WITHOUT END_STREAM - more DATA frames to come */')
->line(' int rv = nghttp2_submit_headers(session, NGHTTP2_FLAG_END_HEADERS,')
->line(' stream_id, NULL, hdrs, 2, NULL);')
->line(' if (rv < 0) return rv;')
->line(' ')
->line(' return nghttp2_session_send(session);')
->line('}')
->blank;
lib/Hypersonic/Stream.pm view on Meta::CPAN
->endif
->blank
->line('s->extra_headers[0] = \'\\0\';')
->if('items >= 3 && SvROK(ST(2)) && SvTYPE(SvRV(ST(2))) == SVt_PVHV')
->line('HV* hv = (HV*)SvRV(ST(2));')
->line('int extra_pos = 0;')
->blank
->comment('Extract Content-Type')
->line('SV** ct = hv_fetchs(hv, "Content-Type", 0);')
->if('!ct')
->line('ct = hv_fetchs(hv, "content-type", 0);')
->endif
->if('ct && *ct')
->line('STRLEN len;')
->line('const char* val = SvPV(*ct, len);')
->if('len < sizeof(s->content_type)')
->line('memcpy(s->content_type, val, len);')
->line('s->content_type[len] = \'\\0\';')
->endif
->endif
->blank
t/0027-chunked-encoding.t view on Meta::CPAN
plan tests => 5;
require XS::JIT::Builder;
my $builder = XS::JIT::Builder->new;
Hypersonic::Protocol::HTTP1->gen_chunked_start($builder);
my $code = $builder->code;
like($code, qr/void send_chunked_headers\(/, 'function defined');
like($code, qr/Transfer-Encoding: chunked/, 'chunked header included');
like($code, qr/Content-Type: %s/, 'content-type placeholder');
like($code, qr/Connection: keep-alive/, 'keep-alive for streaming');
like($code, qr/send\(fd, headers/, 'sends headers');
};
subtest 'gen_chunked_write uses writev' => sub {
plan tests => 4;
require XS::JIT::Builder;
my $builder = XS::JIT::Builder->new;
t/0027-chunked-encoding.t view on Meta::CPAN
plan tests => 3;
require XS::JIT::Builder;
my $builder = XS::JIT::Builder->new;
Hypersonic::Stream->gen_stream_start_c($builder);
my $code = $builder->code;
like($code, qr/Transfer-Encoding: chunked/, 'chunked header');
like($code, qr/HTTP\/1\.1 %d %s/, 'HTTP/1.1 status line');
like($code, qr/Content-Type: %s/, 'content-type included');
};
subtest 'Stream generates chunk writes with writev' => sub {
plan tests => 2;
require XS::JIT::Builder;
my $builder = XS::JIT::Builder->new;
Hypersonic::Stream->gen_stream_write_chunk_c($builder);
my $code = $builder->code;
t/0029-sse.t view on Meta::CPAN
};
subtest 'SSE headers set on start' => sub {
plan tests => 2;
my $mock_stream = MockStream4->new;
my $sse = Hypersonic::SSE->new($mock_stream);
$sse->event(data => 'test');
is($MockStream4::headers_set->{'Content-Type'}, 'text/event-stream', 'content-type set');
is($MockStream4::headers_set->{'Cache-Control'}, 'no-cache', 'cache-control set');
};
# ============================================================
# Test 18-20: RFC compliance edge cases
# ============================================================
subtest 'Event with empty data' => sub {
plan tests => 2;
my $event = Hypersonic::Protocol::SSE->format_event(data => '');
( run in 1.148 second using v1.01-cache-2.11-cpan-524268b4103 )