Racket URL Dispatch Rules
Asked Answered
L

1

5

I'm following the official racket example for URL-based dispatch, but can't seem to get it to work correctly.

#lang web-server/insta  
(require web-server/servlet
         web-server/servlet-env)

(define (start request)
  (blog-dispatch request))

(define-values (blog-dispatch blog-url)
  (dispatch-rules
   (("") list-posts)
   (("posts" (string-arg)) review-post)
   (else list-posts)))

(define (list-posts req) `(list-posts))
(define (review-post req p) `(review-post ,p))

(serve/servlet start
               #:servlet-path ""
               #:port 8080)

When I run the .rkt file, the web server seems to work correctly. But when I actually hit the main page (http://localhost:8080/ or whatever) I get a generic "Welcome to Racket" page instead of the response I specified in the dispatch rules. If I hit localhost:8080/posts/test, I get an error that the page I specified is missing. Am I missing something obvious here?

Libbey answered 22/5, 2016 at 19:59 Comment(0)
H
10

There are a few problems with your code, though not all of them are really your fault. The web-server API is kinda weird, and the serve/servlet API especially so.

First of all, you should not use #lang web-server/insta if you want to use the serve/servlet API directly. Use #lang web-server instead if you want to use stateless servlets, or use #lang racket or #lang racket/base for stateful ones. As your code is currently written, it will use the start function as the entry point for web-server/insta as well as the invokation of serve/servlet, so you’re effectively launching a web server twice.

Second of all, the way serve/servlet works is a little confusing: by default, it only captures requests at the path that you specify with #:servlet-path. I find that this is usually not what I want, so you want to provide #:servlet-regexp #rx"" to allow the servlet to handle requests to any path.

Finally, your servlet functions themselves do not return valid responses. You probably want to return some kind of JSON or HTML. You need to construct a response struct and return that, but you can use helper functions like response/xexpr to do that pretty easily.

With all those changes, your code should look something like this:

#lang racket/base

(require web-server/servlet
         web-server/servlet-env)

(define (start request)
  (blog-dispatch request))

(define-values (blog-dispatch blog-url)
  (dispatch-rules
   (("") list-posts)
   (("posts" (string-arg)) review-post)
   (else list-posts)))

(define (list-posts req)
  (response/xexpr `(html (body "list-posts"))))
(define (review-post req p)
  (response/xexpr `(html (body (div "review-post: " ,p)))))

(serve/servlet start
               #:servlet-path "/"
               #:servlet-regexp #rx""
               #:port 8080)
Halibut answered 23/5, 2016 at 1:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.