Open atgreen opened 5 years ago
I don't see any mention of how method names map to paths.
Heh, I'm quite surprised: the README goes into this at length, it's the main function in Snooze!!
I think you have to decide first what your REST resource is. Is it "API"? If so your route should be
`(defroute api (:get :text/html version string) ...)
And then version
and string
will be bound to the uninterned symbols #v1
and #hello
respectively, in the first case, and #v1
and #test
in the second case. There are ample ways to configure this (see the README).
If however, you want two rest resources: "api/v1/hello" and "api/v1/test", then you should write two routes defining two resources.
(defroute api/v1/hello (:get :text/html &rest arguments-if-you-want-them) ...)
and
(defroute api/v1/test (:get :text/html &rest arguments-if-you-want-them) ...)
When I do this...
(snooze:defroute api/v1/start (:get "text/plain") (setf player-count (+ 1 player-count)) (format nil "~A" player-count))
I get a 404 error. Hunchentoot reports this:
127.0.0.1 - [2018-11-20 08:38:39] "GET /api/v1/start/ HTTP/1.1" 404 13 "-" "Go-http-client/1.1"
Indeed snooze seems to have trouble when the resource name has "/" in it. This seems like a bug, I will take a look at it.
This works for you, right?
(snooze:defroute foo (:get "text/plain") "bar")
And then accessing http://localhost:<yourport>/foo
right?
It's not a bug, it's like this for design. Snooze provides a customization point for your case, snooze:*resource-name-function*
. Here is its doc, which you can find in the api.lisp file:
(defparameter *resource-name-function* 'default-resource-name
"How to search for resource names in URI paths.
Value is a function designator called on every request with the
request's URI path. The function might be called with the empty
string.
This function should return two values: a resource designator (a
string, symbol or a resource) and a relative URI string stripped of the
resource-designating part. If the first value returned is nil,
*HOME-RESOURCE* is used to lookup a suitable resource.
The function should *not* attempt any URI-decoding of the component
string. That is done automatically elsewhere.
The default value is DEFAULT-RESOURCE-NAME, which returns the first
path component as the first value and the remaining URI as the second
value..
Can be let-bound to modify the URI scheme used by a particular
server.")
So you need to write a suitable function for something that will split the string up to three "/" in the string and split it there, returning both parts as separate values
.
Yes, that works.
On Tue., Nov. 20, 2018, 10:29 a.m. João Távora <notifications@github.com wrote:
This works for you, right?
(snooze:defroute foo (:get "text/plain") "bar")
And then accessing http://localhost:
/foo right? — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/joaotavora/snooze/issues/15#issuecomment-440313842, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFfieaB8gl_rV5GWZ9ic35wuy7j-LLxks5uxB_EgaJpZM4Yp8R9 .
Thanks.. I'll have a look later today!
On Tue., Nov. 20, 2018, 10:31 a.m. João Távora <notifications@github.com wrote:
It's not a bug, it's like this for design. Snooze provides a customization point for your case, snooze:resource-name-function. Here is its doc, which you can find in the api.lisp file:
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/joaotavora/snooze/issues/15#issuecomment-440314723, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFfiT06hlS6TCHRNLOqah4Upnuz10xjks5uxCBKgaJpZM4Yp8R9 .
I'm also having some trouble here. I didn't want to create a new ticket.
I hope I didn't overlook something but I've read the readme a few times now.
Basically I have two routes:
(defroute blog (:get :text/html) ;; index
(defroute blog (:get :text/html name) ;; named resource
When compiling this I get an error on the second definition:
Lambda list of method #<STANDARD-METHOD BLOG (SNOOZE-VERBS:GET
SNOOZE-TYPES:TEXT/HTML)>
is incompatible with that of the generic function BLOG.
Method's lambda-list : (SNOOZE-VERBS:HTTP-VERB SNOOZE-TYPES:TYPE)
Generic-function's : (SNOOZE-VERBS:HTTP-VERB SNOOZE-TYPES:TYPE
NAME)
In principle it's clear, two methods with the same name. But my lacking CL knowledge doesn't let me overcome this. Any ideas?
When you use defroute
you are basically writing defmethod
. Just expand it (in sly
it's C-c C-m
on the (
of the defroute. In fact, you can defmethod
directly.
Now, this should be enough to hint that a route in Snooze is only a method in a generic function. So when you do the first blog
you establish a certain protocol for the generic function, when you try to change that protocol, Lisp complains. Most Lisps (I think SBCL at least) give you the option to replace the protocol of the generic function with the new one.
You should learn about "Generic Functions". In Snooze, a REST resource is represented by a generic function. The methods of the generic functions are the different routes that provide access to that resource. Different types of access. Read access is a GET
specializer on the first HTTP-VERB
arg, write access if PUT
or POST
or DELETE
on that arg. And the same with the content types.
Also, in your case, it seems like you want a /blog/<name-of-blog>
route. Ask yourself: is <name-of-blog>
mandatory, or is it optional? If it's optional it should be an &optional
or &key
argument. If it's mandatory, then pointing your browser to just /blog
automatically generates a 400 error, as one would expect.
or is it optional? If it's optional it should be an
&optional
Great. This was a good pointer. Got it working with &optional.
And then version and string will be bound to the uninterned symbols #v1 and #hello respectively, in the first case, and #v1 and #test in the second case. There are ample ways to configure this (see the README).
Are you refering to the uri-to-arguments
method?
I believe you can close this one as well.
Are you refering to the uri-to-arguments method?
Yes, and its counterpart arguments-to-uri
. Whatever you do to uri-to-arguments
you should also do to arguments-to-uri
, so that you can later use blog-path
to generate perfectly matching URIs for your blog
REST resource.
You could also use read-for-resource
and write-for-resource
, if you're concerned with the string representation of all the arguments for a particular resource. Most times, you will want uri-to-arguments
and arguments-to-uri
though, leveraging their default implementations with call-next-method
, of course.
I was hoping to have URIs like...
http://localhost/api/v1/hello http://localhost/api/v1/test
But I see that this doesn't work: (defroute api/v1/hello ...
I don't see any mention of how method names map to paths. How would I do something like this?
Thanks!