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.

Reply via email to