Troubleshooting

Troubleshooting

Here’s a diagram of each part of an OHTTP request:

A diagram of the OHTTP request flow, from client to relay to gateway to application and back.

When debugging an OHTTP connection, you effectively want to check each individual segment of this diagram separately, to figure out exactly where the problem is.

At a high level, you are looking for differences in the requests and responses when talking to the Relay vs talking to the Gateway. You may end up eventually just running the client directly and using a tool like Proxyman to actively intercept the traffic and direct it to the Relay or to the Gateway so that you can compare the requests and responses.

Before doing that much work, here are some starting points for checking each individual segment of the OHTTP request cycle, first.

Client to Relay

The first step is to test your connection to the relay. Can you make an HTTP request to the relay and get a response back successfully?

For example, you can make a request to the relay’s debug endpoint, rather than requesting a relayed response. Our debug endpoint is located at relay.oblivious.network/debug. Here’s an example curl request that verifies a working connection to the relay:

Bash
curl https://relay.oblivious.network/debug -v \
  -H "Content-Type: message/ohttp-chunked-req" \
  -d "body data"
Example relay response
* Host relay.oblivious.network:443 was resolved.
* IPv6: 2606:4700:3030::6815:4f84, 2606:4700:3030::ac43:91bb
* IPv4: 172.67.145.187, 104.21.79.132
*   Trying 172.67.145.187:443...
* Connected to relay.oblivious.network (172.67.145.187) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=oblivious.network
*  start date: Jun  6 04:39:37 2025 GMT
*  expire date: Sep  4 05:39:34 2025 GMT
*  subjectAltName: host "relay.oblivious.network" matched cert's "relay.oblivious.network"
*  issuer: C=US; O=Google Trust Services; CN=WE1
*  SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://relay.oblivious.network/debug
* [HTTP/2] [1] [:method: POST]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: relay.oblivious.network]
* [HTTP/2] [1] [:path: /debug]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [content-type: message/ohttp-chunked-req]
* [HTTP/2] [1] [content-length: 9]
> POST /debug HTTP/2
> Host: relay.oblivious.network
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: message/ohttp-chunked-req
> Content-Length: 9
>
* upload completely sent off: 9 bytes
< HTTP/2 200
< date: Tue, 17 Jun 2025 21:25:58 GMT
< content-type: application/json;charset=UTF-8
< content-length: 2767
< cf-ray: 95159f5d1abffaf4-SJC
< report-to: {"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=5wmWHr7kR6RvfJ%2BtdnKx5QUEiXHrjS4dXVYrCic2SqF%2FiGMV8qq1IUguoAvJjf%2Bq6jOlsfMIr7oWPtqaJtS8yOTYJqCslRgS1nqX28ZOMCS%2FT3ME%2FkwbQ5sqywqD81MZ%2FtOTogqb1PH%2FTw%3D%3D"}],"group":"cf-nel","max_age":604800}
< nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
< server: cloudflare
< alt-svc: h3=":443"; ma=86400
< server-timing: cfL4;desc="?proto=TCP&rtt=7510&min_rtt=6664&rtt_var=2144&sent=8&recv=11&lost=0&retrans=0&sent_bytes=2933&recv_bytes=630&delivery_rate=434573&cwnd=251&unsent_bytes=0&cid=06080ac61b5d8449&ts=291&x=0"
<
{
  "cf": {
    "clientTcpRtt": 7,
    "requestHeaderNames": {},
    "httpProtocol": "HTTP/2",
    "tlsCipher": "AEAD-CHACHA20-POLY1305-SHA256",
    "continent": "NA",
    "asn": 32329,
    "verifiedBotCategory": "",
    "country": "US",
    "isEUCountry": false,
    "region": "California",
    "tlsClientCiphersSha1": "eDGmD1H99AwNYzOR+7eoGLo6eLU=",
    "tlsClientAuth": {
      "certIssuerDNLegacy": "",
      "certIssuerSKI": "",
      "certSubjectDNRFC2253": "",
      "certSubjectDNLegacy": "",
      "certFingerprintSHA256": "",
      "certNotBefore": "",
      "certSKI": "",
      "certSerial": "",
      "certIssuerDN": "",
      "certVerified": "NONE",
      "certNotAfter": "",
      "certSubjectDN": "",
      "certPresented": "0",
      "certRevoked": "0",
      "certIssuerSerial": "",
      "certIssuerDNRFC2253": "",
      "certFingerprintSHA1": ""
    },
    "tlsClientRandom": "UNpBqJQPiRsfp5J7B2OhFj3G8QZstccyNAhapunxxbM=",
    "tlsExportedAuthenticator": {
      "clientFinished": "57ce9f955b7031e0dfc0ef467f5ef7777dab76f7c8b995a21ad339a169d876a2",
      "clientHandshake": "c346304dda840ffb65ce56dc1356707bf3b866d0904a9d477c7430411d2fcd1c",
      "serverHandshake": "a7e9eff47e269063a67bf340e2bda85be4a4cb218cea553f664ad1c49ad5e46e",
      "serverFinished": "0f7fea70484b5eaae3a9dd87d98ec4c2db58ca0e1e3d6112586d83d5b10a9c1b"
    },
    "tlsClientHelloLength": "324",
    "colo": "SJC",
    "timezone": "America/Los_Angeles",
    "longitude": "-122.41530",
    "latitude": "37.75090",
    "edgeRequestKeepAliveStatus": 1,
    "requestPriority": "weight=16;exclusive=0;group=0;group-weight=0",
    "postalCode": "94110",
    "city": "San Francisco",
    "tlsVersion": "TLSv1.3",
    "regionCode": "CA",
    "asOrganization": "Another Corporate ISP, LLC",
    "tlsClientExtensionsSha1Le": "NMNf2YIpLBhtroOEBooGFi+jtJ8=",
    "tlsClientExtensionsSha1": "Ub+nUmIm1U57hdNSUph0R+kx9Gc="
  },
  "url": "https://relay.oblivious.network/debug",
  "urlParts": {
    "origin": "https://relay.oblivious.network",
    "href": "https://relay.oblivious.network/debug",
    "protocol": "https:",
    "host": "relay.oblivious.network",
    "hostname": "relay.oblivious.network",
    "pathname": "/debug",
    "searchParams": {}
  },
  "method": "POST",
  "headers": {
    "accept": "*/*",
    "accept-encoding": "gzip, br",
    "cf-connecting-ip": "170.39.169.133",
    "cf-ipcountry": "US",
    "cf-ray": "95159f5d1abffaf4",
    "cf-visitor": "{\"scheme\":\"https\"}",
    "connection": "Keep-Alive",
    "content-length": "9",
    "content-type": "message/ohttp-chunked-req",
    "host": "relay.oblivious.network",
    "user-agent": "curl/8.7.1",
    "x-forwarded-proto": "https",
    "x-real-ip": "170.39.169.133"
  },
  "body": "body data",
  "target": null
* Connection #0 to host relay.oblivious.network left intact

Relay to Gateway

The Relay server acts as a proxy, forwarding your encrypted HTTP request to the gateway. Hopefully, your gateway will have some sort of debug endpoint that you can use to verify a simple network connection to the gateway.

For example, if you are talking to the Cloudflare OHTTP Gateway, the root endpoint / returns a plaintext description of the server’s other endpoints. Here’s an example using the Oblivious Network demo gateway.

Bash
curl https://demo-gateway.oblivious.network/demo-info -v
Example response directly from Gateway
* Host demo-gateway.oblivious.network:443 was resolved.
* IPv6: 2a09:8280:1::78:557a:0
* IPv4: 66.241.125.169
*   Trying 66.241.125.169:443...
* Connected to demo-gateway.oblivious.network (66.241.125.169) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=demo-gateway.oblivious.network
*  start date: May 28 07:38:44 2025 GMT
*  expire date: Aug 26 07:38:43 2025 GMT
*  subjectAltName: host "demo-gateway.oblivious.network" matched cert's "demo-gateway.oblivious.network"
*  issuer: C=US; O=Let's Encrypt; CN=E5
*  SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://demo-gateway.oblivious.network/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: demo-gateway.oblivious.network]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: demo-gateway.oblivious.network
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< date: Tue, 17 Jun 2025 22:09:56 GMT
< content-length: 305
< content-type: text/plain; charset=utf-8
< server: Fly/2e0083d48 (2025-06-12)
< via: 2 fly.io, 2 fly.io
< fly-request-id: 01JXZZAST51K46HD0J5EJGBMHM-sjc
<
OHTTP Gateway
----------------
Config endpoint: /ohttp-keys
Legacy config endpoint: /ohttp-configs
Target endpoint: /gateway
   Request content type:  message/bhttp request
   Response content type: message/bhttp response
Echo endpoint: /gateway-echo
Metadata endpoint: /gateway-metadata
----------------
* Connection #0 to host demo-gateway.oblivious.network left intact

We have configured a demonstration relay, located at /demo-info, that will proxy requests to the gateway info endpoint. You can use our demo relay to see an example plaintext response from our demo gateway like this.

Bash
curl https://relay.oblivious.network/demo-info -v \
    -H "Content-Type: message/ohttp-req" -X POST
Example response from Client to Relay to Gateway and back
* Host relay.oblivious.network:443 was resolved.
* IPv6: 2606:4700:3030::6815:4f84, 2606:4700:3030::ac43:91bb
* IPv4: 172.67.145.187, 104.21.79.132
*   Trying 172.67.145.187:443...
* Connected to relay.oblivious.network (172.67.145.187) port 443
* ALPN: curl offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=oblivious.network
*  start date: Jun  6 04:39:37 2025 GMT
*  expire date: Sep  4 05:39:34 2025 GMT
*  subjectAltName: host "relay.oblivious.network" matched cert's "relay.oblivious.network"
*  issuer: C=US; O=Google Trust Services; CN=WE1
*  SSL certificate verify ok.
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://relay.oblivious.network/demo-info
* [HTTP/2] [1] [:method: POST]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: relay.oblivious.network]
* [HTTP/2] [1] [:path: /demo-info]
* [HTTP/2] [1] [user-agent: curl/8.7.1]
* [HTTP/2] [1] [accept: */*]
* [HTTP/2] [1] [content-type: message/ohttp-req]
> POST /demo-info HTTP/2
> Host: relay.oblivious.network
> User-Agent: curl/8.7.1
> Accept: */*
> Content-Type: message/ohttp-req
>
* Request completely sent off
< HTTP/2 200
< date: Tue, 17 Jun 2025 22:06:03 GMT
< content-type: message/ohttp-res
< cf-ray: 9515da13ac31fb65-SJC
< access-control-allow-origin: *
< access-control-allow-headers: Cache-Control, Content-Type, Expires, Pragma
< access-control-allow-methods: POST
< report-to: {"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=I4kvvTf9%2BgQunlPvc52edUTj1bEzDaGJrYj5AqxNVNMsOMi8dbz%2FY0KIkuzZWBsz32L44sr5WgeO%2FiNxeMhfOtHe5FrjoTgRt%2BwOLDdKq8RRaDrqLYIPgPk4iE9YtpqoU7UPLAUJp5MsSQ%3D%3D"}],"group":"cf-nel","max_age":604800}
< nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
< server: cloudflare
< alt-svc: h3=":443"; ma=86400
< server-timing: cfL4;desc="?proto=TCP&rtt=8474&min_rtt=5874&rtt_var=4323&sent=8&recv=11&lost=0&retrans=0&sent_bytes=2932&recv_bytes=604&delivery_rate=493020&cwnd=252&unsent_bytes=0&cid=c827e9f5a3a46231&ts=324&x=0"
<
OHTTP Gateway
----------------
Config endpoint: /ohttp-keys
Legacy config endpoint: /ohttp-configs
Target endpoint: /gateway
   Request content type:  message/bhttp request
   Response content type: message/bhttp response
Echo endpoint: /gateway-echo
Metadata endpoint: /gateway-metadata
----------------
* Connection #0 to host relay.oblivious.network left intact

Client to Gateway

Now that we’re sure the network connection from client to gateway is functional, we can start to worry about creating encyrpted payloads to send to the gateway. Oblivious HTTP uses RFC 9292, the Binary HTTP standard, to encode the HTTP request that the Client wants the Gateway to make.

After encoding, the request is also encrypted with the Gateway’s public keys. The response forwarded from the Gateway to the Client will likewise be encoded as a Binary HTTP response (and also be encrpyted to the Client).

Creating a BHTTP encrypted payload for a gateway has a few steps:

  1. Construct an HTTP request to be sent by the Gateway
  2. Encode the request as BHTTP
  3. Fetch Gateway public encryption keys
  4. Encrypt the BHTTP payload using the Gateway keys

Here’s a demo of how to ensure the encryption is working, both directly to the gateway and through the relay to the gateway.

In these demos, we are going to fetch the gateway keys, hex-encode them, and then pass them to the ohttp rust library’s ohttp-client. The request body will be encrypted, sent to the given URL, decrypted by the gateway, and then the exact request body will be re-encrypted back to the client as an “echo” response. The CLI tool will print out the decrypted response, demonstrating that the entire network and encryption path to the gateway and back is functioning correctly.

First, clone a copy of the ohttp repository from GitHub, and make sure you have Rust installed. Compile the library by running cargo build, and you’ll be ready to run these commands.

Bash
cargo run --bin ohttp-client -- -i examples/request.txt \
    https://demo-gateway.oblivious.network/gateway-echo \
    "$(curl https://demo-gateway.oblivious.network/ohttp-keys -s | xxd -p -c 0)"
Example response directly from Gateway
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/ohttp-client 'https://demo-gateway.oblivious.network/gateway-echo' -i examples/request.txt 04c90000300987307db116805a3f7b5195ed7507a870d2556d309e5803920fc6fe24c5493e1edc9cf99563928685c909ba1215c47b622fb916195bf767e7e52119a75d02290c0ce641af5c6ec1900ddba077a6222a408a76e8d0204c759244592e624b3a24f3cdea9b40630976450108203a5076110dbb5a3c960cc1b2e602c2b9964b3631f5dcc6d0eb48627b990a390848e5084e9bac16586de6d12eef4c56d3a233c9541a702530a8e75ef1740a378786c7f76b76a3bc94d7238ac51e2d37cbd14113beb616a76c2bf074839a52abd4d4811a655c2b12bbb519c1180a74ade4afd94823e5971fe928794f4b5f18e8b9993c61c5176ff9864ee6697c662879806b374f393853f50faad3788824989a8b19adf2caae100b797b06cf9b6337712088588db1c405e77ab2edc94f7915c31dca55b53b85feda3f08a41b1d3aa730804bb178cb16fc5d78379c8aeaa0bdb1c160b23a7af9b79c4b6a03cbc98bdac814ba293a5657a077501e0866aa733f2b091382a486eb882520fc7b9a7c20358002d1141d1797c85fb280738c5a015a0e6633326a3481956a69860582637337a0f22a7cca202d6086b9413d6e6477830612715a6202970d19a62867eb5392ea59964b7984267a464a7d73e7a4963b1e40f92429239823bc2cce054df3127b6daab400f66fe596c056722c63126645e4857ab3099f5abd3576c8f8355b645487dbe5c3ef3429090ccfaa193e9d32bb6cc9cbba3482d7960e2b31464d5b5162ec6bf184a1bdd2ab37f2bc20cb38eddc86dd595b70616e8dd9048f0138ce31ba61a0bc5ab9037e792eb22c5f3dbc48ed76885b230d28c16bc0895a5b8067e3141867c97a4d57b3838c539856b40fd9cc89e63e33149c5a6233a10ba3cdf81b9014832a182b74360216c20b81129b9ff1593f770ee4e3abae635213874eab638a52666867f26a0278b27cc271d07011c1d6cb8e9b4d84e42089e4a64925ab8f29cc6faaced4ab1e8e0a8aecd91849eb498ea6c2ab4668fb17a1dd82467c54b9ae922cba627464a90d772c12fac005e61a365eb4b433055a4fd26966467a5c35036e70c189e65f88605c3ed975e062a0a5db591b562168319d6ae34435d42464d99879c03f31676631189092659c73fb377c23cf2cb3c7b62884e9e50ef8da03f3cc35b70739adc2c13d2517aa79804cf2a2c8e1c218db11cf1214522bc02c3276cbd806d192bb1a719d4c132e14b41ffdf33a814ba68a47835dfb5365e088cc00a2259a31b01415a11c7cb1284e2b2c174ce8c1cd914a34a83149f78ce1ba80bbd6b3eca971317aaa365970901c7f6d2927413357e7a56ea702042b905366e8a2a6f53a92c06150c26b44741c070a01bc90c1bd8246fe0c49c638ccef1575f92accd349a017a4688c354f2ef1c879a883ad8844e249b64164a3e0863ffeeb36c7e31adedc74ec838dda5c7cdf8a38936314374247048bcc44c19afae89f364a0506619fde4000b7ab96149284cd956cd28b57fbd80816b9573e769afb051ad5d5c0080286993c5aea85811fc4a8601265bc1532b6c89afff3922939b73d01a10b05882c6a31090324772c4b83927e35331a13168fd442a9aea06cab5aa95e145fa4d8b2c353b61dfcbc40abb73b178c3bb5aed923325fc8afd67475acd3cc2f0b80c1d1b75cd49860538df33fd2e759b1ade3e4cae8e4f84f9f52c0bb30a07d38c6a12dc7c6c71e0004000100010029800020c81d90101968e527b350ca17003e2389de8711843b458b9afeea990dc2188d64000400010001`
Request: 80002000010001a61b83fdebeb9f2743de5c7f6b04f022d91a553144982229e75213fb2a6d0b375d3e8e0133ae7ff7b41ce969b3d0258cfed65d3d3ae0a97c0764bdd5fccb86ec40f7a3329d36dac04adbce2e3b74245a45fe4e18d2f4d891e42422812aee974e36e262a7f78395365649643356da30f8da1ed542483c6fb5c4956cf00dc7da50946b0b0ec5eace92e9ec4a482ce09dc1818e3feb97a23198ef94f5a8adf8861352e3fd4fa3975be9b70427f0ccca421f21f75485c6c9149d0b996c9ad185296ba91bc0bd158e37b1ec
Response: 4f06cff94db656d7900f0aad9172e43fe646f5c238ade6d2c1c369a45f2430ab117ddb9b5bc3cb4f1625fef60ac3ef63c64ab836ff4bb9b4d631b813ae554d61ac77c290ae7949c448cdbe5c10a14c31c49616f03b79b4d318dd32d2e166ee03bcf4e05e25a43e6c76e2ebf6fdd1e4107889c427e93d765cdb7bda70da693ff3f5b1b126d4d203453bc6f1513abae31de77fad247df1f1a0b1533cb791e533f1da0b0fd0950780ede6a9db6e526ea4b685d336cfedb0ddb70e
GET /anything HTTP/1.1
Content-Length: 19
user-agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
host: www.example.com
accept-language: en, mi

request body here
Bash
cargo run --bin ohttp-client -- -i examples/request.txt \
  https://relay.oblivious.network/demo-echo \
  "$(curl https://demo-gateway.oblivious.network/ohttp-keys -s | xxd -p -c 0)"
Example response from Relay to Gateway
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/ohttp-client 'https://relay.oblivious.network/demo-echo' -i examples/request.txt 04c90000300987307db116805a3f7b5195ed7507a870d2556d309e5803920fc6fe24c5493e1edc9cf99563928685c909ba1215c47b622fb916195bf767e7e52119a75d02290c0ce641af5c6ec1900ddba077a6222a408a76e8d0204c759244592e624b3a24f3cdea9b40630976450108203a5076110dbb5a3c960cc1b2e602c2b9964b3631f5dcc6d0eb48627b990a390848e5084e9bac16586de6d12eef4c56d3a233c9541a702530a8e75ef1740a378786c7f76b76a3bc94d7238ac51e2d37cbd14113beb616a76c2bf074839a52abd4d4811a655c2b12bbb519c1180a74ade4afd94823e5971fe928794f4b5f18e8b9993c61c5176ff9864ee6697c662879806b374f393853f50faad3788824989a8b19adf2caae100b797b06cf9b6337712088588db1c405e77ab2edc94f7915c31dca55b53b85feda3f08a41b1d3aa730804bb178cb16fc5d78379c8aeaa0bdb1c160b23a7af9b79c4b6a03cbc98bdac814ba293a5657a077501e0866aa733f2b091382a486eb882520fc7b9a7c20358002d1141d1797c85fb280738c5a015a0e6633326a3481956a69860582637337a0f22a7cca202d6086b9413d6e6477830612715a6202970d19a62867eb5392ea59964b7984267a464a7d73e7a4963b1e40f92429239823bc2cce054df3127b6daab400f66fe596c056722c63126645e4857ab3099f5abd3576c8f8355b645487dbe5c3ef3429090ccfaa193e9d32bb6cc9cbba3482d7960e2b31464d5b5162ec6bf184a1bdd2ab37f2bc20cb38eddc86dd595b70616e8dd9048f0138ce31ba61a0bc5ab9037e792eb22c5f3dbc48ed76885b230d28c16bc0895a5b8067e3141867c97a4d57b3838c539856b40fd9cc89e63e33149c5a6233a10ba3cdf81b9014832a182b74360216c20b81129b9ff1593f770ee4e3abae635213874eab638a52666867f26a0278b27cc271d07011c1d6cb8e9b4d84e42089e4a64925ab8f29cc6faaced4ab1e8e0a8aecd91849eb498ea6c2ab4668fb17a1dd82467c54b9ae922cba627464a90d772c12fac005e61a365eb4b433055a4fd26966467a5c35036e70c189e65f88605c3ed975e062a0a5db591b562168319d6ae34435d42464d99879c03f31676631189092659c73fb377c23cf2cb3c7b62884e9e50ef8da03f3cc35b70739adc2c13d2517aa79804cf2a2c8e1c218db11cf1214522bc02c3276cbd806d192bb1a719d4c132e14b41ffdf33a814ba68a47835dfb5365e088cc00a2259a31b01415a11c7cb1284e2b2c174ce8c1cd914a34a83149f78ce1ba80bbd6b3eca971317aaa365970901c7f6d2927413357e7a56ea702042b905366e8a2a6f53a92c06150c26b44741c070a01bc90c1bd8246fe0c49c638ccef1575f92accd349a017a4688c354f2ef1c879a883ad8844e249b64164a3e0863ffeeb36c7e31adedc74ec838dda5c7cdf8a38936314374247048bcc44c19afae89f364a0506619fde4000b7ab96149284cd956cd28b57fbd80816b9573e769afb051ad5d5c0080286993c5aea85811fc4a8601265bc1532b6c89afff3922939b73d01a10b05882c6a31090324772c4b83927e35331a13168fd442a9aea06cab5aa95e145fa4d8b2c353b61dfcbc40abb73b178c3bb5aed923325fc8afd67475acd3cc2f0b80c1d1b75cd49860538df33fd2e759b1ade3e4cae8e4f84f9f52c0bb30a07d38c6a12dc7c6c71e0004000100010029800020c81d90101968e527b350ca17003e2389de8711843b458b9afeea990dc2188d64000400010001`
Request: 80002000010001af8812702686551005f78f13496ad627f9058ea6ae6c37eff81feb4c9c9fc276efbdd3aab428e80d2b46d48ff320f3a0ea3c658c0c4fa3183a6a40040798835f42c03d5f3524b2b39f3d3b865e4606612a9c770be2a1e947b1bd9f65cbe511c962d258c5725f9e49a53ae8ef994f92d9bd8fe9cdeb9860226abd275db00e3c3f8a6f217a6097111fa59dad4f650b6ae26831adca8a6082a403ba35c3043762ccbd35e3d68fd4c5a4b3256f96212d8a951cfa111ac93373cab63830922c1873991f59b3c7ac2ad70674
Response: 9b3520d3e8249debab9750b33335fc73695f21fed56eb43d46cb6d63cf5c0863dca72d9a3a0b8de475e05531cb2b22946baa05438d0ae3eb18ec0e71d400c8d6e14cc2db39acfe208575ae4a17609df38897883e8a4485fc1a72c89434b9b21f393caaca7fd01cea2a0b6438ed896306f6e7323c6a8e79d33f28ef241ba36620cfdad3b9edab538104ca9d8af7db49e391d86b00e9b11211468e407fd2dd1f10fecc5e165391ad96a8db995d0737af2a78064d275da29a56d7
GET /anything HTTP/1.1
Content-Length: 19
user-agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
host: www.example.com
accept-language: en, mi

request body here

Gateway to Service

Finally, we want to validate that the decrypted HTTP requests can be made by the gateway, and the response can be encrypted and sent back to the client. We can verify this by sending our request to the regular gateway endpoint, rather than the gateway echo endpoint, and by altering the example request to use an actual service that the gateway can talk to.

First, let’s create an actual HTTP request for the Gateway to make on our behalf:

Bash
cat <<EOF | sed 's/$/\r/' > examples/service-request.txt
GET https://httpbin.oblivious.network/anything HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

request body here
EOF

Now that we have an example request, let’s try sending that request to the Gateway, both directly and through the Relay.

Bash
cargo run --bin ohttp-client -- -i examples/service-request.txt \
  https://demo-gateway.oblivious.network/gateway \
  "$(curl https://demo-gateway.oblivious.network/ohttp-keys -s | xxd -p -c 0)"
Example response to Service directly via Gateway
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/ohttp-client 'https://demo-gateway.oblivious.network/gateway' -i examples/service-request.txt 04c90000300987307db116805a3f7b5195ed7507a870d2556d309e5803920fc6fe24c5493e1edc9cf99563928685c909ba1215c47b622fb916195bf767e7e52119a75d02290c0ce641af5c6ec1900ddba077a6222a408a76e8d0204c759244592e624b3a24f3cdea9b40630976450108203a5076110dbb5a3c960cc1b2e602c2b9964b3631f5dcc6d0eb48627b990a390848e5084e9bac16586de6d12eef4c56d3a233c9541a702530a8e75ef1740a378786c7f76b76a3bc94d7238ac51e2d37cbd14113beb616a76c2bf074839a52abd4d4811a655c2b12bbb519c1180a74ade4afd94823e5971fe928794f4b5f18e8b9993c61c5176ff9864ee6697c662879806b374f393853f50faad3788824989a8b19adf2caae100b797b06cf9b6337712088588db1c405e77ab2edc94f7915c31dca55b53b85feda3f08a41b1d3aa730804bb178cb16fc5d78379c8aeaa0bdb1c160b23a7af9b79c4b6a03cbc98bdac814ba293a5657a077501e0866aa733f2b091382a486eb882520fc7b9a7c20358002d1141d1797c85fb280738c5a015a0e6633326a3481956a69860582637337a0f22a7cca202d6086b9413d6e6477830612715a6202970d19a62867eb5392ea59964b7984267a464a7d73e7a4963b1e40f92429239823bc2cce054df3127b6daab400f66fe596c056722c63126645e4857ab3099f5abd3576c8f8355b645487dbe5c3ef3429090ccfaa193e9d32bb6cc9cbba3482d7960e2b31464d5b5162ec6bf184a1bdd2ab37f2bc20cb38eddc86dd595b70616e8dd9048f0138ce31ba61a0bc5ab9037e792eb22c5f3dbc48ed76885b230d28c16bc0895a5b8067e3141867c97a4d57b3838c539856b40fd9cc89e63e33149c5a6233a10ba3cdf81b9014832a182b74360216c20b81129b9ff1593f770ee4e3abae635213874eab638a52666867f26a0278b27cc271d07011c1d6cb8e9b4d84e42089e4a64925ab8f29cc6faaced4ab1e8e0a8aecd91849eb498ea6c2ab4668fb17a1dd82467c54b9ae922cba627464a90d772c12fac005e61a365eb4b433055a4fd26966467a5c35036e70c189e65f88605c3ed975e062a0a5db591b562168319d6ae34435d42464d99879c03f31676631189092659c73fb377c23cf2cb3c7b62884e9e50ef8da03f3cc35b70739adc2c13d2517aa79804cf2a2c8e1c218db11cf1214522bc02c3276cbd806d192bb1a719d4c132e14b41ffdf33a814ba68a47835dfb5365e088cc00a2259a31b01415a11c7cb1284e2b2c174ce8c1cd914a34a83149f78ce1ba80bbd6b3eca971317aaa365970901c7f6d2927413357e7a56ea702042b905366e8a2a6f53a92c06150c26b44741c070a01bc90c1bd8246fe0c49c638ccef1575f92accd349a017a4688c354f2ef1c879a883ad8844e249b64164a3e0863ffeeb36c7e31adedc74ec838dda5c7cdf8a38936314374247048bcc44c19afae89f364a0506619fde4000b7ab96149284cd956cd28b57fbd80816b9573e769afb051ad5d5c0080286993c5aea85811fc4a8601265bc1532b6c89afff3922939b73d01a10b05882c6a31090324772c4b83927e35331a13168fd442a9aea06cab5aa95e145fa4d8b2c353b61dfcbc40abb73b178c3bb5aed923325fc8afd67475acd3cc2f0b80c1d1b75cd49860538df33fd2e759b1ade3e4cae8e4f84f9f52c0bb30a07d38c6a12dc7c6c71e0004000100010029800020c81d90101968e527b350ca17003e2389de8711843b458b9afeea990dc2188d64000400010001`
Request: 80002000010001976d1c2e5699c32248936d7b27fbe86c5231ba7dbcdc6f53f67deb08eddf7437573a89339ba7bf4e366985298b860cfeec1d2761bff17eaf4a30540c6b77e3e43e97cc3ddd4525c9d826d6bb6dd2023252ccaf18e0919b586af0e1cf90b42805a54e23250dd90fd98a348e81b1840f05c4e7570c0c2ff9784bb2e39ab4b77b4e141f27c9d87e4a51c8317f810a73f4481689a2e84927f40323a3e375fd90ea3f8d190852dd2bac685eb5bdaeb95c3c7440d0cc2e89881ac337bb7f035cb9804aff9e9df171c003dc6cd3afaa96767487ff54ee01532d635a26a41f23acd0334e51d6
Response: 20717400396c2a66f2e7847f005860b506fb69b72f0448dc93f8d4139271a9d9cc8b3813a3e27ba20f52affe99a17d28d1ec0d5f54628ef6f3e96736cd3fefcb7e792a05b2c467d1d864b4fc5619608d24c615c09257e56aa1d506dcc473437cfcbe68726ec181483438c883a7fa7d78135811a6d056c1704324c78c40f50ae873b93e5002bf2d2e2fb48bb0ce4261e7f86c7bbb8268366e2a095229b2a117145d88580c751ab2df62809d926f7ca59b845a0cfa895255487b11dc3b8560a6fe68c370c44c49498a34e09ab2c9c34d596ccd103efcd3d77c388300eee443347d39bf6c66a51530583a54514f27f7e9e10cc6e5acbfd7a06d08cabca03be5b1c991af3bc25e3aa6c72bf8a4ddd1d0aeb8d57366564421b14a146896b467088a7c124c0e8e3350ced3ccae662da017338ae50340fece200afa26feeb5b36cce54a55044f2685fe365c69d393ccd335a97deea6f40884d464ab05bdfe20ddc4654d219475330ee7a5fea14394784bce4dd9e952590096e1c7c87bcfadba932cb90245296892feb343bd0ff61a20707b62cd54a51df89d9d5b5a1a412d16a4d09da81002b0b749aa1e262981b825969b696f549602b55b623cfda403be726527a5864a83e382b85c0cd86387c9ef9f8948776334f3dc69183333d8221382934b9c85b16fe1f8ab97ce885b86e88e8d87b2eafebe07100e2bf06368f1dd2e3fac5d7168a1f6270d86dcae328e861c5a4edad2e7c907a12ed025a927bb9fd30f6079345470f2701c045e24d724a307214345b2251aa0e947529f444c3544bda6b00dc61dcec0803893a9449681fb32ad510783cfe65d0cc78ba01ea3d0bcf625a36d8bdb543bd67d58d754b6228bebfea5fcd30f401b5a9cb711bb0fbc236f8928dd1410549e7688e5c01695d573f7e02497099cb902d6b97286d16154fa81d2d13e3cc6dc5f4df58ce03878d39d60c5a720f6bdaa7155a84bea592e36dad2343a9963d623d147c353c5e65eeab729b35ba720a6eb35e60efb892ea5ea45928a9df8f394bbabf0f95ebe6dc47c80503b82cda96ec605fed627733bddfe5d4d3d50070956c24d24a3cc3adc882f4f0113d4db31a609c3b4afec4c73034615d56a205665e2e7349ff0f627b2a0edf6bd1b9bcf64223ae370fa0d016010641c985441646103e4a3061c364b3dabc8ef45c1a8c324469a6541b683bcaad16f9871fab9705ef7628967dfa133aa4114b93070ede0c416f571928a9c9c98db15d49ec9428f878f20fda4a5a80d7931a4ee1e64a3d9565dcf0d62fe345e5f2172cc79233b7c57a29e4e325671672a900ec8326f38c17d5ea88579c4617dc1248e8de0a4d82c329cc04301fb7b4cb7c5f569c9ff980ed9df3a83a11fbac8fb24984e067423b321068bd04a94ef337227fa0d83ca807942003be5b0a25484799fa74696146530b842f5f5c5106607ce72e9be49d49af4a8663fb64f912431441ba4fb4d2b95f4cb7494c3c96d8051bd70e9d71404c3ea8964145ee8aa18c5912b2a160b34673f893e89cfb6e7fab33abf87468c394e2f315b9a1e9ebd0da3e4fcd96f4ee9be9d6ffd7d8bfa63ebd874c09d0a575a0d08a11c480eb2ce4f129bece5cbdc11475e65861564134db80d3ace1b20fae6e438b3f8cea0ce315406a6e9f015f6affd4376f93e5ba97620619434747c47e5c8de01906cf3e431cfd5de549f98d357d14806fb9e980614e7214dc807c0b8df80789f5caa5f318c0cdaea0495c200c6a254becbd47d14004c32b5225784d7f0e9d8c46fe5eaf9506be3f9f5cc00e4ee716dd7fcc5f37f9fa52089fe7f0f276e2073015d35d1be36715448223806f79569c13bf790369addf3e60fa2ac48e7293d889f1934bda35378a3ebacd8c1d4e193295d51845eac5909b1446539cc61b4ac
HTTP/1.1 200 Reason
Content-Length: 954
access-control-allow-credentials: true
x-request-id: ec8d30bb-6b8c-4045-a133-b1d21c8e5c71
date: Tue, 17 Jun 2025 23:10:14 GMT
server: Fly/2e0083d48 (2025-06-12)
via: 2 fly.io
fly-request-id: 01JY02GKTKTDJW34HGVSWK9JHA-lax
content-type: application/json
vary: origin, access-control-request-method, access-control-request-headers accept-encoding
server-timing: total;dur=0

{
  "method": "GET",
  "uri": "/anything",
  "headers": {
    "accept-encoding": "gzip",
    "accept-language": "en, mi",
    "content-length": "19",
    "fly-client-ip": "2605:4c40:104:74ab:0:e5b0:edee:1",
    "fly-forwarded-port": "443",
    "fly-forwarded-proto": "https",
    "fly-forwarded-ssl": "on",
    "fly-region": "lax",
    "fly-request-id": "01JY02GKTKTDJW34HGVSWK9JHA-lax",
    "host": "httpbin.oblivious.network",
    "user-agent": "curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3",
    "via": "2 fly.io",
    "x-forwarded-for": "2605:4c40:104:74ab:0:e5b0:edee:1, 2a09:8280:1::6f:a4ce:0",
    "x-forwarded-port": "443",
    "x-forwarded-proto": "https",
    "x-forwarded-ssl": "on",
    "x-request-id": "ec8d30bb-6b8c-4045-a133-b1d21c8e5c71",
    "x-request-start": "t=1750201814867981"
  },
  "origin": "2605:4c40:104:74ab:0:e5b0:edee:1",
  "args": {},
  "data": "request body here\r\n",
  "json": null,
  "form": {},
  "files": {}
}
Bash
cargo run --bin ohttp-client -- -i examples/service-request.txt \
    https://relay.oblivious.network/demo \
    "$(curl https://demo-gateway.oblivious.network/ohttp-keys -s | xxd -p -c 0)"
Example response from Service via Gateway via Relay
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Running `target/debug/ohttp-client 'https://relay.oblivious.network/demo' -i examples/service-request.txt 04c90000300987307db116805a3f7b5195ed7507a870d2556d309e5803920fc6fe24c5493e1edc9cf99563928685c909ba1215c47b622fb916195bf767e7e52119a75d02290c0ce641af5c6ec1900ddba077a6222a408a76e8d0204c759244592e624b3a24f3cdea9b40630976450108203a5076110dbb5a3c960cc1b2e602c2b9964b3631f5dcc6d0eb48627b990a390848e5084e9bac16586de6d12eef4c56d3a233c9541a702530a8e75ef1740a378786c7f76b76a3bc94d7238ac51e2d37cbd14113beb616a76c2bf074839a52abd4d4811a655c2b12bbb519c1180a74ade4afd94823e5971fe928794f4b5f18e8b9993c61c5176ff9864ee6697c662879806b374f393853f50faad3788824989a8b19adf2caae100b797b06cf9b6337712088588db1c405e77ab2edc94f7915c31dca55b53b85feda3f08a41b1d3aa730804bb178cb16fc5d78379c8aeaa0bdb1c160b23a7af9b79c4b6a03cbc98bdac814ba293a5657a077501e0866aa733f2b091382a486eb882520fc7b9a7c20358002d1141d1797c85fb280738c5a015a0e6633326a3481956a69860582637337a0f22a7cca202d6086b9413d6e6477830612715a6202970d19a62867eb5392ea59964b7984267a464a7d73e7a4963b1e40f92429239823bc2cce054df3127b6daab400f66fe596c056722c63126645e4857ab3099f5abd3576c8f8355b645487dbe5c3ef3429090ccfaa193e9d32bb6cc9cbba3482d7960e2b31464d5b5162ec6bf184a1bdd2ab37f2bc20cb38eddc86dd595b70616e8dd9048f0138ce31ba61a0bc5ab9037e792eb22c5f3dbc48ed76885b230d28c16bc0895a5b8067e3141867c97a4d57b3838c539856b40fd9cc89e63e33149c5a6233a10ba3cdf81b9014832a182b74360216c20b81129b9ff1593f770ee4e3abae635213874eab638a52666867f26a0278b27cc271d07011c1d6cb8e9b4d84e42089e4a64925ab8f29cc6faaced4ab1e8e0a8aecd91849eb498ea6c2ab4668fb17a1dd82467c54b9ae922cba627464a90d772c12fac005e61a365eb4b433055a4fd26966467a5c35036e70c189e65f88605c3ed975e062a0a5db591b562168319d6ae34435d42464d99879c03f31676631189092659c73fb377c23cf2cb3c7b62884e9e50ef8da03f3cc35b70739adc2c13d2517aa79804cf2a2c8e1c218db11cf1214522bc02c3276cbd806d192bb1a719d4c132e14b41ffdf33a814ba68a47835dfb5365e088cc00a2259a31b01415a11c7cb1284e2b2c174ce8c1cd914a34a83149f78ce1ba80bbd6b3eca971317aaa365970901c7f6d2927413357e7a56ea702042b905366e8a2a6f53a92c06150c26b44741c070a01bc90c1bd8246fe0c49c638ccef1575f92accd349a017a4688c354f2ef1c879a883ad8844e249b64164a3e0863ffeeb36c7e31adedc74ec838dda5c7cdf8a38936314374247048bcc44c19afae89f364a0506619fde4000b7ab96149284cd956cd28b57fbd80816b9573e769afb051ad5d5c0080286993c5aea85811fc4a8601265bc1532b6c89afff3922939b73d01a10b05882c6a31090324772c4b83927e35331a13168fd442a9aea06cab5aa95e145fa4d8b2c353b61dfcbc40abb73b178c3bb5aed923325fc8afd67475acd3cc2f0b80c1d1b75cd49860538df33fd2e759b1ade3e4cae8e4f84f9f52c0bb30a07d38c6a12dc7c6c71e0004000100010029800020c81d90101968e527b350ca17003e2389de8711843b458b9afeea990dc2188d64000400010001`
Request: 80002000010001fda48ee51a4b2e76b7cbbc5c68da8e5715e6801c8f6494a6cdbf631434653e4dbf2a396dc71adbd4730c1f2e8e2b43fbe65b424f6960bc9324235f69b3b9f6f94a7bc0fab100f3b55e9efe66659ab5d3ba5897b024d38bd80c8f2ae012a599fafd4458b7c0b91c9bfea8b18fa855011ae96d5afaf5edabea4f106b7eacda09e10993fd63033a1b90f4aa5c6182955d6a9b7a2bc726fcabeb810949a051dc1251031b9a1ae49e014fcd401502739a4e8b644fa02d4c038e118f5c7142c123c86c9f61bc0a29abf6a34c90748364aec7649c168459a5b0e5547e35fca60b1bd816940c
Response: f4a90fd37b69856dd7ec1f425698ed88049d6d493446da7d52c8e92781b8626315d1b4c23d3f1b2617b05b0d5caf4d7a08a508ebedafab5bee88a67dde494e2aab544aa5b176d80f8238948e672787963e9bbb85646972175b48fe08dcec71b7078255d64ce5d531abacab07db49d24dfc2b3686b25299aff1edd30c128aed5e1a350c909055545e4786eae73246da3e62b6a27eb07f47037304aa5344e6c7a144ea18f09d75ac623a640cb374d84f998c441513ce0af9659481dd025b2261814735e8e946d28ff17f111d0af0a5fb83a621486ddebfc4fd92b862f285411f57edf14c1f6c485469790a4a1c79b0fcda9f26677e01b74c67369e171fc7c6ce2447119024de3b29b853b576b6c7634e394431237312b441c9553f93239bd4ba2a685bc2c307e8276b0925b1a2d53e34400e3124e7f73ae335ee38657a16dff11bcc0c9d574ce4425cb8fb858004d3af71e06f2bc2c2259030ad8071e6cb54ce27505db4052b40245c3e9b6ac366cf290814d9e9e6d1dbbd3bf6ace9e1efe88e92802dd7b8268b8851ee35f24d75956c8bdaadcaf768885347abd1f57fa41e867973e22c0545dc5e9ec1a6807e756811d26d8abf550f33179832775cc49ba3b1c74aae99736f47de5a34f81e534763b32c6ab4deb5694ba534aacaf4747b54b0307973814572f90c7654b721f881c546f64615792ab15f475ac8c835204fbd4cd223707cdb1aaf856379303543b663c9078fe46c13e8a42fa2782683da5bc7523dd98160b90aea1b910f54ae1ba2f06f77e83d43bc6f5987d03ad0e346abcceb7e8eecc536dbc9facbf2e5c206b59d4ffdafe680f24da4fc52f4ccc1e90720927b8b94a39449c90ced4862d4709a9037d0aca64ba6c214ace37304fc5da32fa93d86265a8c494512ad7677395ea72572f8da8745b03120184c88d9c17ad4d2e270ce23d42ad1bf62babe640f1a4f274668483751bdcc673d5d230afde153c1805ba753ae49ff9aa9b6bf47c689b240b980588605a5451532e1f60b6b0b6a6381c2e52d4eeaefccd25f5fee810d2b3a71df190c4be6a5b0c15139e9adce453c016043d25593dfe52faa98fdabfb3ab7a856f9ddccb751cc342d31aa7df8c06e0d5c61c7bd0d0a2c1884ba5aba76635985fd6ce64ab199d3ade95daa7432cd171fa42ab494c31ebe28b1315fa7d51314aac0249f2ebef94b90ce49063e4f7303853ec0dd867bc630d1e1cf755e44cd88c4cd2f1504d68d2a5ac24acd936256dbff641edd53f2445cdd634d2bd3cd54dd73fca9fb392e1ebe57aa443174976ba366d931f3fd6794169e84a7e1132d19d14336159e060e9b73c572e43b06cd08a9e5958d98631eb2bdefc18956999fc095c068792b2cc77e98ccd1dd7697d4304adcc5a74e8d523f989e11a255005e6e9a59d06b44e1ad01487cab5593333f150ba234971a5e1089dc4d9eb04c728aa97202e24aab980b681add3c592b063957644ee5d07bb6f525a8e4a3c826c769f65f7c534daf3f7c4129258898bcb6e503a0bcb38c847d472bbb3281753139eb4881b83063875d39723523b1058e919d84a836649648bfd908ec186644d897d6cbecc54b08816a4283e28c072cc537bb57cc68878b40f44becf528b5463493ce9c9ba65e6afaa926e5c55526d515059829737c3e862cb740e4b1e71c54671e66db5440afef1fbba8ce71cb156f1d11479924b81dd54e7f69bdf186a5e2960f2ebd91b74d3cae7dd6012cfedfdeea168071f461e322797310acb38b75450933b952c77c0efc11b7102bec67a5d40a4c00777afbeea5b9fbc2904ac38d5c8bf84da093378c439c81fcbf92cedefe5ea59c0cdd2ea5302ff70c4ecdaf1d46605d723eceaeca38d167fda0cb48de076a5b75f880e1d8fa8ff6825e529858b09ce27db794
HTTP/1.1 200 Reason
Content-Length: 954
content-type: application/json
server-timing: total;dur=0
x-request-id: a8629e9d-9b18-4e70-a34f-cec8fbc82bc5
server: Fly/2e0083d48 (2025-06-12)
via: 2 fly.io
vary: origin, access-control-request-method, access-control-request-headers accept-encoding
access-control-allow-credentials: true
date: Tue, 17 Jun 2025 23:06:19 GMT
fly-request-id: 01JY02EW74PRBD9YDSWJX06FKS-lax

{
  "method": "GET",
  "uri": "/anything",
  "headers": {
    "accept-encoding": "gzip",
    "accept-language": "en, mi",
    "content-length": "19",
    "fly-client-ip": "2605:4c40:104:74ab:0:e5b0:edee:1",
    "fly-forwarded-port": "443",
    "fly-forwarded-proto": "https",
    "fly-forwarded-ssl": "on",
    "fly-region": "lax",
    "fly-request-id": "01JY02EW74PRBD9YDSWJX06FKS-lax",
    "host": "httpbin.oblivious.network",
    "user-agent": "curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3",
    "via": "2 fly.io",
    "x-forwarded-for": "2605:4c40:104:74ab:0:e5b0:edee:1, 2a09:8280:1::6f:a4ce:0",
    "x-forwarded-port": "443",
    "x-forwarded-proto": "https",
    "x-forwarded-ssl": "on",
    "x-request-id": "a8629e9d-9b18-4e70-a34f-cec8fbc82bc5",
    "x-request-start": "t=1750201757924305"
  },
  "origin": "2605:4c40:104:74ab:0:e5b0:edee:1",
  "args": {},
  "data": "request body here\r\n",
  "json": null,
  "form": {},
  "files": {}
}%

At this point, you have hopefully seen the response from httpbin.oblivious.network printed out, demonstrating that the Client, Relay, and Gateway are all functioning correctly.

Still broken?

If you’re still having trouble, there are few remaining things to investigate.

Is it CORS?

If you’re making any of these requests from inside a web browser, or from inside a WASM environment, it’s possible that the relay isn’t correctly providing CORS headers. Before every request to the Relay, the browser will send an HTTP OPTIONS request, to find out if the relay allows requests from the website that the client is running on.

Use your browser devtools and console to see if any of the requests are failing due to CORS, and if that’s the case, update your Relay configuration to allow your service as an origin. Ensure that all responses from the Relay, including both OPTIONS and POST responses, include at least this header:

Access-Control-Allow-Origin:

For more information about the allowed values for the header, see the MDN docs for Access-Control-Allow-Origin.

Is it the content type?

Relays and Gateways only accept requests with the content type message/ohttp-req or message/ohttp-chunked-req, and they only accept responses with the content type message/ohttp-res or message/ohttp-chunked-res. You might have a content type mismatch in the client or gateway, or the relay might not be configured correctly.

Is anything different between direct to the gateway and going through the relay? You won’t be able to see the “far side” of traffic from the relay to the gateway, but sometimes just being able to see the full debug version of the requests and responses is enough to identify differences.

If you have Proxyman installed, you can intercept traffic going in both directions in order to compare the full request and response values.

Finally, support tickets

If none of this has worked, that’s a good sign to send an email to support@oblivious.network, including the requests and responses you’ve used to debug. Usually, if you can show a difference between making the exact same request to the relay or directly to the gateway, that means the relay has a bug and we’ll need to get it fixed.