fukamachi / clack

Web server abstraction layer for Common Lisp
MIT License
1.05k stars 86 forks source link

Fail to parse a JSON Body with a Space. #58

Closed PuercoPop closed 9 years ago

PuercoPop commented 11 years ago

Disclaimer: I'm not sure if the error is in the yason library's skip-whitespace method or in the clack package. But because the test case requieres ningle & clack I figured I report it here. By the way, I think the parsing the body with yason and storing it as an extra env attribute should probably be implemented as a middleware.

So bare bones test case is defining an endpoint that just spits the env out

(setf (ningle:route *app* "/word/" :method :PUT)
      #'(lambda (params)
          (format nil "~a" (slot-value ningle:*request* 'clack.request::env))))

and then hit the endpoint with curl:

 => curl -v -XPUT -H"Content-Type: application/json" -d "{\"cat\": \"dog\"}" http://localhost:5000/word/

and I get the following error (note that if I remove - H option the endpoint works fine):

#\  fell through ECASE expression.
Wanted one of (#\t #\f #\n #\[ #\{ #\- #\0 #\1 #\2 #\3 #\4 #\5
               #\6 #\7 #\8 #\9 #\").
   [Condition of type SB-KERNEL:CASE-FAILURE]
Restarts:
 0: [ABORT] Abort thread (#<THREAD "hunchentoot-worker-127.0.0.1:55430" RUNNING {100892DA93}>)

Upon inspecting the #\ symbol the slime inspector shows me the following:

#<STANDARD-CHAR {2049}>
--------------------
Char code: 32
Lower cased: @0=#\ 
Upper cased: @0=#\ 

It appears to be whitespace, but that is weird as the parse% method is supposed to skip-whitespace

(ecase (peek-char-skipping-whitespace input)
    (#\"
     (parse-string input))
    ((#\- #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
     (parse-number input))

    (#\{
     (parse-object input))
    (#\[
     (parse-array input))
    ((#\t #\f #\n)
     (parse-constant input)))))

;; ======
(defun peek-char-skipping-whitespace (input &optional (eof-error-p t))
  (skip-whitespace input)
  (peek-char nil input eof-error-p))

(defun skip-whitespace (input)
  (loop
     while (and (listen input)
                (whitespace-p (peek-char nil input)))
     do (read-char input)))

(defun whitespace-p (char)
  (member char '(#\Space #\Newline #\Tab #\Linefeed #\Return)))

Also, I checked that #\ and #\Space are equivalent

(member #\ '(#\Space))

* (eq #\Space #\ )
T

P.D. Thank you not only for your libraries but also because of your strong focus on documentation (even if it not done yet)

fukamachi commented 11 years ago

I could reproduce this error. Still I can't understand why it occurs.

PuercoPop commented 11 years ago

Yeah I don't have a clear picture either, it could be a encoding related issue. When I use drakma to send the HTTP request (which uses utf-8 instead of latin-1 by default) I don't get the error. I plan to investigate further during the weekend.

fukamachi commented 9 years ago

I'm closing this because I think this is resolved accidentally in Clack v1.0. (Clack v1.0 uses HTTP-Body to parse application/json by jsown.)

Feel free to reopen this if you still have this problem.