FAQs: Web Server - racket/racket GitHub Wiki

See also: Web Development

How to deploy on Heroku

See https://lexi-lambda.github.io/blog/2015/08/22/deploying-racket-applications-on-heroku/

How to deal with cookies

  1. You can pass base64 encoded values to the browser as cookie-values as long as you strip out both the embedded and trailing carriage-return-line-feed sequences.

    The following code is incorrect because there are carriage-return-line-feed sequences.

    (define (start request)
      (response/xexpr 
       `(html (head (meta ((name "viewport") (content "initial-scale=1.0, user-scalable=no")))
                    (meta ((http-equiv "content-type") (content "text/html; charset=UTF-8"))))
              (body (div "Cookies!")))
       #:headers 
       (list (make-header #"Set-Cookie" 
                          #"Racketboy=XetM5o+My2BQYizra/y+NC7UJ0MxMjM0\r\nNTY2OQ==\r\n; Secure;"))))

    To fix the problem, adjust the cookie value to #"Racketboy=XetM5o+My2BQYizra/y+NC7UJ0MxMjM0NTY2OQ==; Secure;"

  2. The Secure flag in the cookie only instructs the browser not to send the cookie over a non-secure connection. The server will happily pass a Secure-flag cookie over a non-secure connection.

To prevent the a Secure-flag cookie from being sent over a non secure connection, set the #:ssl keyword argument to #t in serve/servlet.

How to build a response to an HTTPXmlRequest

Note: the correct MIME-type is important to get the browser to understand what you're sending over in the body of the response.

Client-side convention with respect to setting up client AJAX continuation seems to be to at least check the message-field equal to "OK", so be aware of this.

In addition to this code, You still need to send the response back to the client via one of Jay McCarthy's primitives such as send/suspend/dispatch (if stateless), or send/back (if stateful).

#|
USAGE: 
(define res (make-xml-response `(xml "victory!")))
(call-with-output-string (response-output res))
-> "<xml>victory!</xml>"

|#
#lang racket
(require xml
         web-server/servlet-env
         web-server/http/response-structs
         web-server/http/request-structs)

;; or just use #lang web-server and (require xml), if that's easier for you

(define (make-xml-response  #:code [code 200]
                            #:message [message #"OK"]
                            #:seconds [seconds (current-seconds)]
                            #:mime-type [mime-type #"text/xml charset=utf-8"]
                            #:headers [headers (list (make-header #"Cache-Control" #"no-cache"))]
                            content)
  (response/full code message seconds mime-type headers (list (string->bytes/utf-8 (xexpr->string content)))))

How to setup AJAX functionality

This doesn't do very much, but you can use as an AJAX test bed. I used this particular code to test whether setting browser cookies via AJAX works.

#lang web-server
  
(require web-server/servlet-env
         web-server/http/xexpr
         xml)

(define my-xml-response
  (response/xexpr `(xml "victory!")
                  #:mime-type #"text/xml charset=utf-8"
                  #:headers (list (make-header #"Set-Cookie" #"name=mikey"))))
  
(define (start request)
  (letrec ((response-generator (λ (make-url)
                                 (response/xexpr `(html (head 
                                                         (script ((type "text/javascript")) ,(format StartXMLHttpRequest (make-url receive-ajax-signal)))
                                                         (script ((type "text/javascript")) ,processChange))
                                                        (body (div ((onclick "alert('things are working');"))  "Hello jay")
                                                                     (div ((onclick "StartXMLHttpRequest('some data');"))  "click for AJAX-type Request")
                                                                     (a ((href ,(make-url receive-signal)))"click for browser-window-type Request"))))))
           (receive-ajax-signal   (λ (request)
                                    my-xml-response))
           (receive-signal (λ (request)
                              (send/suspend/dispatch response-generator))))
    (send/suspend/dispatch response-generator)))


(define StartXMLHttpRequest (string-append "function StartXMLHttpRequest(post_data){ "
                                           "obj = new XMLHttpRequest(); "
                                           "obj.onreadystatechange = processChange;"
                                           "obj.open('POST','~A',false); "
                                           "obj.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); "
                                           "obj.send(post_data); "
                                           "processChange();"
                                            "} "))
                 
(define processChange "function processChange(){alert('in processChange!');}")
                                           
(serve/servlet start
               #:stateless? #t        
               #:launch-browser? #t
               #:connection-close? #t
               #:quit? #f 
               #:listen-ip #f 
               #:port 8000
               #:servlet-path "/")
⚠️ **GitHub.com Fallback** ⚠️