paivana

HTTP paywall reverse proxy
Log | Files | Refs | Submodules | README | LICENSE

README (6299B)


      1 paivana reverse-proxy tests
      2 ===========================
      3 
      4 This directory contains an integration test suite for the reverse-proxy
      5 side of paivana-httpd.  All tests run paivana-httpd with `-n`
      6 (paywall disabled) so no merchant backend is required: they only
      7 verify that the proxy correctly forwards HTTP requests and responses.
      8 
      9 What gets built
     10 ---------------
     11 
     12 The test suite uses four diverse upstream HTTP server implementations
     13 so that paivana is not exercised only against libmicrohttpd peers:
     14 
     15   upstream_mhd   C / libmicrohttpd  (built always)
     16   upstream_go    Go (net/http)      (built if `go`    is found)
     17   upstream_rs    Rust (std::net)    (built if `rustc` is found)
     18   upstream_py    Python (stdlib)    (pure interpreter; needs python3
     19                                      at `make check` time)
     20 
     21 They all implement the same canned endpoints (see "Endpoints" below).
     22 The pipelining test client `pipeline_client` is a small C program
     23 that talks directly to the paivana listen socket using BSD sockets.
     24 
     25 Layout of the driver
     26 --------------------
     27 
     28 `test_reverse_proxy.sh` is the single test program automake runs.
     29 For each available upstream (mhd / go / py / rs) it:
     30 
     31   1. starts the upstream on a fixed port,
     32   2. starts paivana-httpd -n pointed at that upstream,
     33   3. runs a battery of HTTP tests with curl, wget, and the raw-socket
     34      pipelining client,
     35   4. stops paivana and moves on to the next upstream.
     36 
     37 Cross-cutting error-path tests (405, 413, 502) are also covered, and
     38 the final case restarts paivana pointed at a dead port to exercise
     39 upstream-failure handling.
     40 
     41 What each test covers
     42 ---------------------
     43 
     44 Per-upstream battery (`run_battery`):
     45 
     46   GET /hello                  happy-path GET, body proxied unchanged
     47   GET /status/201             2xx response status is forwarded intact
     48   GET /status/404             4xx response status is forwarded intact
     49   GET /status/500             5xx response status is forwarded intact
     50   HEAD /hello                 HEAD method: headers only, no body
     51   GET /large/131072           128 KiB binary response body streams
     52                               through paivana intact (length check)
     53   POST /echo                  request body is forwarded unchanged;
     54                               body round-trip
     55   POST /upload (64 KiB)       large random POST upload; upstream
     56                               reports the byte count it saw
     57   PUT /put                    PUT method + body forwarding
     58   PATCH /patch                PATCH method + body forwarding
     59                               (paivana sets CUSTOMREQUEST)
     60   DELETE /item/1              DELETE method, 204 No Content
     61   OPTIONS /hello              OPTIONS method, Allow header survives
     62                               the round-trip
     63   GET /echo-headers           paivana adds the reverse-proxy headers
     64                               X-Forwarded-For, X-Forwarded-Proto, Via
     65   custom X-Test header        arbitrary client request headers are
     66                               forwarded unchanged
     67   X-Upstream response header  upstream response headers survive the
     68                               round-trip back to the client
     69 
     70 Cross-cutting tests (run once):
     71 
     72   TRACE method                unsupported HTTP verb yields 405 Method
     73                               Not Allowed (paivana rejects it, the
     74                               upstream is never contacted)
     75   2 MiB POST upload           request bodies above the 1 MiB
     76                               REQUEST_BUFFER_MAX are rejected with
     77                               413 Content Too Large
     78   curl keep-alive x3          three GETs over one keep-alive TCP
     79                               connection all succeed
     80   wget /hello                 third-party client interop
     81   HTTP/1.1 pipelining (x4)    four requests sent back-to-back on a
     82                               single TCP connection *before* reading
     83                               any response; responses must come back
     84                               in the same order and with the correct
     85                               status codes (200, 201, 200, 404).
     86                               This specifically tests that paivana's
     87                               per-request state machine and MHD's
     88                               keep-alive handling cooperate correctly.
     89   upstream down               with paivana pointed at a closed port,
     90                               clients receive 502 Bad Gateway with
     91                               the built-in "Bad Gateway" HTML body
     92 
     93 Environment variables
     94 ---------------------
     95 
     96 The driver script honors:
     97 
     98   PAIVANA_HTTPD   path to paivana-httpd (default: the in-tree build)
     99   SRCDIR          directory containing the upstream sources and the
    100                   conf template (default: dirname of the script)
    101   BUILDDIR        directory containing upstream_mhd, pipeline_client,
    102                   upstream_go, upstream_rs (default: $PWD)
    103   KEEP_TMP=1      do not delete the scratch dir on exit
    104 
    105 Ports used
    106 ----------
    107 
    108 All ports are in the 184xx / 185xx range to avoid collisions with
    109 real services.  They are fixed; the suite exits early if any of them
    110 are already in use.
    111 
    112   18401    upstream_mhd
    113   18402    upstream_go
    114   18403    upstream_py
    115   18404    upstream_rs
    116   18499    dead port (for "upstream down" test)
    117   18500    paivana-httpd
    118 
    119 Endpoints (implemented by every upstream)
    120 -----------------------------------------
    121 
    122   GET /hello                  text "Hello from <name>\n"
    123   GET /status/NNN             respond with status NNN and a trivial
    124                               text body "status NNN\n"
    125   GET /large/N                N bytes of 'A'..'Z' repeating
    126   GET /slow/N                 sleep N ms, then "slept\n"
    127   GET /echo-headers           text listing of received request
    128                               headers, "Key: Value\n" per line
    129   POST /echo                  body is echoed verbatim
    130   POST /upload                "Received N bytes\n"
    131   PUT /put                    "PUT received N\n"
    132   PATCH /patch                "PATCH received N\n"
    133   DELETE /item*               204 No Content
    134   OPTIONS *                   204 + Allow: GET, POST, PUT, ...
    135 
    136 Every response also carries an `X-Upstream:` header whose value
    137 identifies which server handled it (mhd, go, py, rs); the client
    138 test cases use it to confirm that responses are coming back from
    139 the expected backend.