2

I have been following Racket's tutorial on building Web servlets, while also reading the documentation on writing Web Applications in Racket. I have tried to simplify the example in the tutorial, while also following the advice in the Web documentation that "you want to use Stateless Servlets for the improved scalability".

My simplified example just shows a list of numbers and allows the user to add a number to the list via an input form. Arriving at the section on Advanced Control Flow in the tutorial, where the "send/suspend/dispatch" mechanism is explained, I tried out my example app, and found that adding an extra number worked, but the embedded URL that is shown in the browser holds a lot of information, including the full path of my script, that I would prefer to keep secret in a production environment. Here is are two examples of the URLs I mean:

http://localhost:8080/;(("c"%20.%20"0((3)%203%20(((lib%20%5C"web-server%2Flang%2Fabort-resume.rkt%5C")%20.%20%5C"lifted.3%5C")%20((lib%20%5C"web-server%2Flang%2Fweb-cells.rkt%5C")%20.%20deserialize-info:frame-v0)%20(%23%5C"%2FUsers%2Flogc%2FDocuments%2Fcode%2Fpersonal%2Fracket%2Fapp%2Fservlet.rkt%5C"%20.%20%5C"lifted.142%5C"))%200%20()%20()%20(0%20(1%20(h%20-%20()))%20(c%20(v!%20(2%20(q%201%202%203))%20%23f%20%23f))))"))?number=12
http://localhost:8080/;(("c"%20.%20"0((3)%203%20(((lib%20%5C"web-server%2Flang%2Fabort-resume.rkt%5C")%20.%20%5C"lifted.3%5C")%20((lib%20%5C"web-server%2Flang%2Fweb-cells.rkt%5C")%20.%20deserialize-info:frame-v0)%20(%23%5C"%2FUsers%2Flogc%2FDocuments%2Fcode%2Fpersonal%2Fracket%2Fapp%2Fservlet.rkt%5C"%20.%20%5C"lifted.142%5C"))%200%20()%20()%20(0%20(1%20(h%20-%20()))%20(c%20(v!%20(2%20(c%20(u%20.%20%5C"12%5C")%20q%201%202%203))%20%23f%20%23f))))"))?number=45

Here is the full code of my simplification of the tutorial app. I just divided the code in two files, "servlet.rkt" to hold the handler functions and "serve.rkt" to launch the servlet.

serve.rkt:

#lang racket
(require "servlet.rkt"
         web-server/servlet-env)

(serve/servlet app
               #:port 8080
               #:stateless? #t
               #:command-line? #t
               #:servlet-path "/")

servlet.rkt:

#lang web-server
(require web-server/http)
(provide interface-version stuffer app)
(define interface-version 'stateless)
(define stuffer
  (stuffer-chain
   serialize-stuffer
   (md5-stuffer (build-path (find-system-path 'home-dir) ".urls"))))

(define CONTENTS
  (list 1 2 3))

(define (app req)
  (render-number-list CONTENTS req))

(define (render-number-list numbers req)
  (define (response-generator embed/url)
    (response/xexpr
      `(html
         (body (h1 "Contents")
               (form
                 ((action ,(embed/url insert-number-handler)))
                 (input  ((name "number")))
                 (input  ((type "submit"))))
               (ul ,@(map render-number numbers))))))
  (define (insert-number-handler req) 
    (render-number-list
      (cons (extract-binding/single 'number (request-bindings req)) numbers)
      req))
  (send/suspend/dispatch response-generator))

(define (render-number number)
  `(li ,(format "~a" number)))

For what it's worth, I used a shell script to execute serve.rkt.

bin/app:

#!/bin/sh
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
racket $DIR/../serve.rkt

My questions are: is this (long list of informations in the embedded URL) avoidable? Did I misconfigure something? Is this somehow related to the fact that I tried to make this servlet stateless, or is this unrelated?

Related questions (Racket URL dispatch, How to show different content based on the path in Racket web servlets?) show a different way of solving the problem, which I probably will try out, but I still would like to know whether this passed URL is by design, and whether stateless servlets in Racket generally work this way (or I made a mistake).

Community
  • 1
  • 1
logc
  • 3,813
  • 1
  • 18
  • 29

1 Answers1

1

I think this has to be like it is, because of it being stateless on the server. The state has to be somewhere and that is in the URL. The server will then react on the information provided in the request, the actual URL being part of the request. Then the server will return something to the client, which in turn again contains all the needed state, so that the client can make a useful request again, putting it all in the URL again.

Zelphir Kaltstahl
  • 5,722
  • 10
  • 57
  • 86