view release on metacpan or search on metacpan
eg/envoy-stream.yaml view on Meta::CPAN
"@type": type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport
config:
version: V2
transport_socket:
name: envoy.transport_sockets.raw_buffer
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer
load_assignment:
cluster_name: feersum_proxy_protocol
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 5000
# Add more for load balancing:
# - endpoint:
# address:
# socket_address:
# address: 127.0.0.1
# port_value: 5001
# Health check (TCP connect)
health_checks:
- timeout: 5s
interval: 10s
unhealthy_threshold: 3
eg/envoy-stream.yaml view on Meta::CPAN
#-------------------------------------------------------------------------
# Plain TCP backend (no PROXY Protocol)
#-------------------------------------------------------------------------
- name: feersum_tcp
type: STATIC
connect_timeout: 5s
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: feersum_tcp
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 5000
#-------------------------------------------------------------------------
# Unix socket backend with PROXY Protocol v2
#-------------------------------------------------------------------------
- name: feersum_unix_proxy_protocol
type: STATIC
eg/envoy-stream.yaml view on Meta::CPAN
"@type": type.googleapis.com/envoy.extensions.transport_sockets.proxy_protocol.v3.ProxyProtocolUpstreamTransport
config:
version: V2
transport_socket:
name: envoy.transport_sockets.raw_buffer
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer
load_assignment:
cluster_name: feersum_unix_proxy_protocol
endpoints:
- lb_endpoints:
- endpoint:
address:
pipe:
path: /tmp/feersum.sock
admin:
address:
socket_address:
address: 127.0.0.1
port_value: 9901
eg/envoy.yaml view on Meta::CPAN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http_protocol_options:
header_key_format:
proper_case_words: {}
load_assignment:
cluster_name: feersum_tcp
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 5000
# Add more for load balancing:
# - endpoint:
# address:
# socket_address:
# address: 127.0.0.1
# port_value: 5001
# - endpoint:
# address:
# socket_address:
# address: 127.0.0.1
# port_value: 5002
# Health check (optional)
health_checks:
- timeout: 5s
interval: 10s
unhealthy_threshold: 3
eg/envoy.yaml view on Meta::CPAN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http_protocol_options:
header_key_format:
proper_case_words: {}
load_assignment:
cluster_name: feersum_unix
endpoints:
- lb_endpoints:
- endpoint:
address:
pipe:
path: /tmp/feersum.sock
admin:
address:
socket_address:
address: 127.0.0.1
port_value: 9901
eg/healthcheck.pl view on Meta::CPAN
#!/usr/bin/env perl
# Health check endpoint example for Docker / load balancers.
#
# GET /health returns 200 immediately even when the app is busy.
# All other paths go through the normal (potentially slow) app handler.
#
# Docker:
# HEALTHCHECK --interval=5s CMD curl -f http://localhost:5000/health
#
use strict;
use warnings;
use Feersum;
eg/multi-instance.pl view on Meta::CPAN
#!/usr/bin/env perl
# Two independent servers in one process, which is what new_instance() is for.
# Feersum->endjinn is a singleton with one handler and one set of tunables;
# new_instance() gives you a second of each, sharing only the event loop.
#
# Here: a public API on 5002 with tight limits, and an admin endpoint on 5003
# with its own handler, its own limits, and its own idea of keepalive.
#
# perl eg/multi-instance.pl
# curl localhost:5002/ ; curl localhost:5003/stats
use strict;
use warnings;
use EV;
use Feersum;
use IO::Socket::INET;
eg/sse-server.pl view on Meta::CPAN
my $path = $req->env->{PATH_INFO};
if ($path eq '/' || $path eq '/index.html') {
# Serve HTML page
$req->send_response(200, [
'Content-Type' => 'text/html; charset=utf-8',
'Cache-Control' => 'no-cache',
], \$html_page);
}
elsif ($path eq '/events') {
# SSE endpoint
start_sse_stream($req);
}
else {
$req->send_response(404, ['Content-Type' => 'text/plain'], \"Not Found\n");
}
});
sub start_sse_stream {
my $req = shift;
my $id = ++$client_id;
eg/ssl-proxy/backend.pl view on Meta::CPAN
unless ($n) { undef $w; close $io; return }
$frame->append($buf);
while (defined(my $msg = $frame->next)) {
my $reply = Protocol::WebSocket::Frame->new(buffer => "echo: $msg")->to_bytes;
syswrite $io, $reply;
}
};
return;
}
# Info endpoint - shows connection info including PROXY protocol data
elsif ($path eq '/info') {
my @lines = (
"=== Connection Info (from PROXY Protocol) ===",
"REMOTE_ADDR: $env->{REMOTE_ADDR}",
"REMOTE_PORT: $env->{REMOTE_PORT}",
"psgi.url_scheme: $env->{'psgi.url_scheme'}",
"",
"=== Request Headers ===",
);
push @lines, map { "$_: $env->{$_}" } sort grep /^(REQUEST_|PATH_|SERVER_|HTTP_)/, keys %$env;
eg/ssl-proxy/run.pl view on Meta::CPAN
chdir "$FindBin::Bin/../..";
system 'eg/ssl-proxy/gen-cert.sh' unless -f 'eg/ssl-proxy/server.crt';
my $backend = fork // die; exec $^X, '-Iblib/lib', '-Iblib/arch', 'eg/ssl-proxy/backend.pl' unless $backend;
sleep 1;
my $stunnel = fork // die; exec 'stunnel', 'eg/ssl-proxy/stunnel.conf' unless $stunnel;
$SIG{$_} = sub { kill 9, $backend, $stunnel; exit } for qw(INT TERM);
print "Backend PID: $backend\n";
print "Stunnel PID: $stunnel\n";
print "\nTest endpoints:\n";
print " curl -k https://localhost:8443/ # Home page\n";
print " curl -k https://localhost:8443/info # Connection info (shows PROXY protocol data)\n";
waitpid -1, 0 while wait > 0;
lib/Feersum.pm view on Meta::CPAN
NonBlocking=true
User=www-data
Group=www-data
See C<eg/systemd-socket.pl> for socket activation code.
=head2 Docker
HEALTHCHECK --interval=5s CMD curl -sf http://localhost:5000/health
See C<eg/healthcheck.pl> for a health check endpoint pattern.
=head2 Reverse Proxy
Feersum works behind nginx, HAProxy, Caddy, or Envoy. See C<eg/nginx.conf>,
C<eg/haproxy.cfg>, C<eg/Caddyfile>, C<eg/envoy.yaml> for example configs.
Enable C<reverse_proxy> or C<proxy_protocol> as appropriate.
=head2 Zero-Downtime Restart
For a B<PSGI> app use L<Plack::Handler::Feersum>:
picotls-git/include/picotls.h view on Meta::CPAN
/**
* global variables exposed
*/
extern struct st_ptls_log_t {
/**
* if application-data (e.g., payload) should be emitted as well
*/
volatile unsigned may_include_appdata : 1;
/**
* endpoints that want to disable logging entirely can provide this value to the loggers
*/
ptls_log_conn_state_t dummy_conn_state;
/**
* generation counter that is incremented whenever the state of loggers change; see `st_ptls_log_state_t::generation`
*/
volatile uint64_t _generation;
} ptls_log;
/**
* initializes a ptls_log_conn_state_t. `conn_id` and `peeraddr` (of type struct sockaddr) are optional; pass 0 and NULL
picotls-git/lib/picotls.c view on Meta::CPAN
if ((ret = call_on_client_hello_cb(tls_cbarg, ch->server_name, raw_message, ch->cipher_suites, ch->alpn.list,
ch->alpn.count, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 1)) != 0)
return ret;
}
return PTLS_ALERT_PROTOCOL_VERSION;
}
/* Check TLS 1.3-specific constraints. Hereafter, we might exit without calling on_client_hello. That's fine because this CH is
* ought to be rejected. */
if (ch->legacy_version <= 0x0300) {
/* RFC 8446 Appendix D.5: any endpoint receiving a Hello message with legacy_version set to 0x0300 MUST abort the handshake
* with a "protocol_version" alert. */
return PTLS_ALERT_PROTOCOL_VERSION;
}
if (!(ch->compression_methods.count == 1 && ch->compression_methods.ids[0] == 0))
return PTLS_ALERT_ILLEGAL_PARAMETER;
/* pre-shared key */
if (ch->psk.hash_end != NULL) {
/* PSK must be the last extension */
if (!ch->psk.is_last_extension)
return PTLS_ALERT_ILLEGAL_PARAMETER;
t/h2-03-edge-cases.t view on Meta::CPAN
$sock->close();
exit($got_error ? 0 : 2);
}, timeout_mult => TIMEOUT_MULT);
is $body_received, 0,
'handler never received the oversized body';
# ========================================================================
# Administrative limits produce a real HTTP status on H2, as on H1, not a
# stream reset with INTERNAL_ERROR (which RFC 9113 reserves for the endpoint's
# own faults and which leaves the client with no status at all).
# ========================================================================
$evh->max_uri_len(200);
h2_fork_test("H2 over-long :path answers 414", $port, sub {
my ($port) = @_;
my $sock = h2_connect($port) or exit(1);
my $headers_block = hpack_encode_headers(
[':method', 'GET'],
t/h2-10-write-timeout.t view on Meta::CPAN
my $wt = 1.0 * TIMEOUT_MULT;
$evh->write_timeout($wt);
# The writer must OUTLIVE the handler: if it goes out of scope its DESTROY
# completes the response, so nothing ever stalls and the timeout cannot fire.
my @keep_writers;
# Streaming response that writes once then stops - should trigger timeout
$evh->request_handler(sub {
my $r = shift;
my $path = $r->env->{PATH_INFO} // '';
if ($path eq '/ok') { # control endpoint, answers normally
$r->send_response(200, ['Content-Type' => 'text/plain'], ['CONTROLOK']);
return;
}
my $w = $r->start_streaming(200, ['Content-Type' => 'text/plain']);
$w->write("hello");
push @keep_writers, $w;
# Intentionally never write again and never close - let timeout fire
});
# nghttp will get a partial response then RST_STREAM (or connection close)
t/native-07-return-from-io-wrong-handle.t view on Meta::CPAN
last if defined $cl && length($body) >= $cl;
last if !defined $cl;
}
}
close $s;
return $buf;
}
# --- 1. wrong handle handed back ---
my $got = talk(proxy_v2() . "GET /wrong HTTP/1.1\r\nHost: x\r\n\r\n");
like $got // q{}, qr{^HTTP/1\.1\ 200}x, 'takeover endpoint answered';
my ($body) = ($got // q{}) =~ /\r\n\r\n(.*)\z/s;
isnt $body, 'NO-CROAK', 'return_from_psgix_io rejected the wrong handle'
or diag 'it accepted a handle wrapping a different descriptor';
like $body // q{}, qr/does not wrap this connection/,
'and said why' or diag "croak was: " . ($body // 'undef');
# --- 2. PROXY v2 trailing TLV fragment ---
# One valid TLV (type 0x03, 1 byte) then a 2-byte tail that cannot be a header.
my $good_tlv = "\x03" . pack('n', 1) . "\xff";
my $ok_resp = talk(proxy_v2($good_tlv)