I have implemented a small reverse proxy in Racket, also based on http-sendrecv/url. It is mostly for a specific application (I know there are some considerations I have not addressed), but I can list some considerations I've encountered along the way:
- A proxy is supposed to remove "hop-by-hop" headers from both the request and the response. These are the headers '(#"Connection" #"TE" #"Transfer-Encoding" #"Keep-Alive" #"Proxy-Authorization" #"Proxy-Authentication" #"Trailer" #"Upgrade") and any headers listed in the Connection header, if present. - You are always building the response with a status of 200. I use a simple regexp to split the status result from http-sendrecv/url into the number and byte-string needed to build the response. I think that might be sufficient to support redirects if the application redirects to relative URLs; otherwise, you need to re-write the Location header. - I see that you are always removing the Host header. From what I remember, applications are finicky about this: I believe I have encountered some that only work correctly if the Host header is preserved and others that only work correctly if it is removed. - If any of your POST requests use multipart/form-data (e.g. for file uploads), that is not preserved in `request-post-data/raw` and would need to be reconstructed from the `request-bindings/raw`. See this discussion: https://groups.google.com/d/topic/racket-users/Pps8boI1pKw/discussion I can give more details if this is relevant to you. - I found that I needed to remove and replace the headers '(#"X-Forwarded-For" #"X-Forwarded-Host" #"X-Forwarded-Server" #"X-Real-IP" #"X-Forwarded-Proto") - Is there a reason you are providing `empty` for your response headers? - I use #f as the mime argument to `response` and have the mime type come from the headers. - I don't know how much difference it makes, but I use `copy-port` to avoid reading the whole response into intermediate bytes. - I've found it useful to wrap `http-sendrecv/url` in a `with-handlers` that constructs a response with status code 500 (internal server error) and information for debugging. Eventually I'd like to clean up my code and post it as a package. -Philip On Sat, Feb 17, 2018 at 7:36 AM, Andrea Giardina <andrea.giard...@gmail.com> wrote: > Hi all, > I'd need to write a very simple reverse proxy and I'm wondering what's > the best way to do it in racket. I don't have any requirements but > performance (not even security and reliability, since I'm writing > basically a testing tool). > > I came out with this solution (using http-sendrecv/url). It seems > working properly for everything but redirects: > > (define (handle-file-request req) > (define uri (request-uri req)) > (define method (request-method req)) > (define post-data (request-post-data/raw req)) > (define proxy-headers > (map > (lambda (h) (bytes-append (header-field h) #": " (header-value h))) > (filter (lambda (h) (not (bytes=? (header-field h) #"Host"))) > headers))) > > (let-values > ([(status headers in) > (http-sendrecv/url > (struct-copy url uri [scheme remote-scheme)] [host > remote-host] [port remote-port]) > #:method method > #:headers proxy-headers > #:data post-data)]) > > (let ([mime (findf identity (map (lambda (h) (extract-field > #"content-type" h)) headers))]) > (response > 200 #"OK" > (current-seconds) (if mime mime #"text/javascript; > charset=UTF-8") > empty > (λ (client-out) (write-bytes (port->bytes in) client-out))))) > > > Do you think is this one the right way or do you think there is a > better (cleaner/more performing) approach? Any idea about how to > manage redirects if not manually? > > Thanks, > Andrea > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.