Attempts to parse a proxy header from the tcp_stream. If none is found or it is unable to be parsed None will be returned. If a header is found it will be returned and its bytes will be removed from the stream. It is possible an invalid header was sent, if that is the case any downstream service will be responsible for returning errors to the client.
(&mut self)
| 87 | /// any downstream service will be responsible for returning errors |
| 88 | /// to the client. |
| 89 | pub async fn take_proxy_header_address(&mut self) -> Option<ProxiedAddress> { |
| 90 | // 1024 bytes is a rather large header for tcp proxy header, unless |
| 91 | // if the header contains TLV fields or uses a unix socket address |
| 92 | // this could easily be hit. We'll use a 1024 byte max buf to allow |
| 93 | // limited support for this. |
| 94 | let mut buf = [0u8; 1024]; |
| 95 | let len = match self.tcp_stream.peek(&mut buf).await { |
| 96 | Ok(n) if n > 0 => n, |
| 97 | _ => { |
| 98 | debug!("Failed to read from client socket or no data received"); |
| 99 | return None; |
| 100 | } |
| 101 | }; |
| 102 | |
| 103 | // Attempt to parse the header, and log failures. |
| 104 | let (header, hlen) = match ProxyHeader::parse( |
| 105 | &buf[..len], |
| 106 | ParseConfig { |
| 107 | include_tlvs: false, |
| 108 | allow_v1: false, |
| 109 | allow_v2: true, |
| 110 | }, |
| 111 | ) { |
| 112 | Ok((header, hlen)) => (header, hlen), |
| 113 | Err(proxy_header::Error::Invalid) => { |
| 114 | debug!("Proxy header is invalid. This is likely due to no header being provided",); |
| 115 | return None; |
| 116 | } |
| 117 | // Data matches the PROXY v2 signature prefix but the header |
| 118 | // is incomplete — likely split across TCP segments. Read the |
| 119 | // 16-byte fixed v2 header to learn the total size, then read |
| 120 | // the remaining address bytes. |
| 121 | Err(proxy_header::Error::BufferTooShort) => { |
| 122 | return self.read_proxy_v2_header(&mut buf).await; |
| 123 | } |
| 124 | Err(e) => { |
| 125 | debug!("Proxy header parse error '{:?}', ignoring header.", e); |
| 126 | return None; |
| 127 | } |
| 128 | }; |
| 129 | debug!("Proxied connection with header {:?}", header); |
| 130 | let address = header.proxied_address().map(|a| a.to_owned()); |
| 131 | // Proxy header found, clear the bytes. |
| 132 | let _ = self.read_exact(&mut buf[..hlen]).await; |
| 133 | address |
| 134 | } |
| 135 | |
| 136 | /// Fallback path for [`Self::take_proxy_header_address`] when the initial |
| 137 | /// peek returned an incomplete PROXY v2 header. Reads the fixed 16-byte |
no test coverage detected