Discussion:
[racket] Problem with response/output
André Matheus
2015-03-06 23:48:35 UTC
Permalink
Hi, starting a project of mine, I've setup a dispatch rule and a function to return the response.
To make things simple, I've used response/output, with a lambda writing to the output-port.
However, I've got the error:

response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
contract from:
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
context...:
/usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12

So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.

I think maybe the contract is wrong but frankly I don't understand much about contracts.

I've setup some code that exposes the problem. Navigating to "/working" and "/fixed" works
fine; navigating to "/not-working" exposes the problem.

#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)

(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))

(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))

(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))

(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))

(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))

(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))

(module+ main
(main))

The contracts in response-structs.rkt:

(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])

Is the contract wrong or am I doing something weird?

Thanks,

André
Matthew Butterick
2015-03-07 00:26:18 UTC
Permalink
Post by André Matheus
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
The contract, by definition, is always right ;)

In this case, `response/output` takes as its first argument a procedure
that accepts an output-port and returns void. [1] In contract-speak this is
commonly written with dot notation as:

(output-port? . -> . void?)

but it appears in error messages, like the one above, with the equivalent
notation:

(-> output-port? void?)

Note also that the error says the contract violation was "in the range of
the 1st argument of" ... [giant contract follows]. That helps track down
the error. The contract for the first argument is '(-> output-port?
void?)'. This is a procedure contract. And "the range of" a procedure
contract means the contract on the return value. Which in this case is
`void?`. So the complaint is that the procedure given in the first argument
is returning '11' when it should be returning void.

Why is (-> output-port? void?) the contract for the first arg of
`response/output`? The idea is that you write to the output-port directly
rather than returning a value to the caller. Insisting on void as a return
value imposes an extra measure of discipline, and sets an expectation.

The reason your 'not-working' dispatcher is not working is that
`write-bytes` does two things: it sends bytes to the output port, but then
also returns the number of bytes written. [2] So this procedure:

(λ (op) (write-bytes #"Hello world" op))

is defective because it returns the number of bytes. Meaning, it breaks the
contract, which demands void. (That's also why your error is '11': that's
the number of bytes in "Hello world").

But your revised procedure:

(λ (op) (write-bytes #"Hello world" op) (void))

Meets the contract because it ignores the return value from `write-bytes`
and returns (void) instead.

You should repeat this technique whenever you use `response/output`.

You can also look into `response/full` and `response/xexpr`, which can be a
more convenient way of making simple HTML or text responses.



[1]
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29

which cross-references

http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29

[2]
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29

which cross-references

http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29
Post by André Matheus
Hi, starting a project of mine, I've setup a dispatch rule and a function
to return the response.
To make things simple, I've used response/output, with a lambda writing to the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
/usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
I've setup some code that exposes the problem. Navigating to "/working" and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof
header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users
Alexis King
2015-03-07 00:40:31 UTC
Permalink
I do sort of agree that the void? requirement is strange and unneeded. It’s usually only used to indicate that a function provided by some module returns #<void>, but callback functions are usually specified with any as the return value to allow precisely this sort of thing.
Post by André Matheus
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
The contract, by definition, is always right ;)
(output-port? . -> . void?)
(-> output-port? void?)
Note also that the error says the contract violation was "in the range of the 1st argument of" ... [giant contract follows]. That helps track down the error. The contract for the first argument is '(-> output-port? void?)'. This is a procedure contract. And "the range of" a procedure contract means the contract on the return value. Which in this case is `void?`. So the complaint is that the procedure given in the first argument is returning '11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of `response/output`? The idea is that you write to the output-port directly rather than returning a value to the caller. Insisting on void as a return value imposes an extra measure of discipline, and sets an expectation.
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks the contract, which demands void. (That's also why your error is '11': that's the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from `write-bytes` and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can be a more convenient way of making simple HTML or text responses.
[1] http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29 <http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29>
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29 <http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29>
[2] http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29 <http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29>
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29 <http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29>
Hi, starting a project of mine, I've setup a dispatch rule and a function to return the response.
To make things simple, I've used response/output, with a lambda writing to the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
/usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
I've setup some code that exposes the problem. Navigating to "/working" and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users <http://lists.racket-lang.org/users>
____________________
http://lists.racket-lang.org/users
Matthew Butterick
2015-03-07 01:16:36 UTC
Permalink
Curiously, the contract for `response` also requires an (-> output-port?
void?) procedure [1]. The source code agrees. But the examples given in the
docs don't include a (void) return value. Yet they do work. So perhaps
there's a tiny bug where `response` is being more lenient than it's
supposed to be.


[1]
http://docs.racket-lang.org/web-server/http.html?q=response#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
Post by Alexis King
I do sort of agree that the void? requirement is strange and unneeded.
It’s usually only used to indicate that a function provided by some module
returns #<void>, but callback functions are usually specified with any as
the return value to allow precisely this sort of thing.
From the error message, I changed the lambda to return (void) and then it
Post by André Matheus
worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
The contract, by definition, is always right ;)
In this case, `response/output` takes as its first argument a procedure
that accepts an output-port and returns void. [1] In contract-speak this is
(output-port? . -> . void?)
(-> output-port? void?)
Note also that the error says the contract violation was "in the range of
the 1st argument of" ... [giant contract follows]. That helps track down
the error. The contract for the first argument is '(-> output-port?
void?)'. This is a procedure contract. And "the range of" a procedure
contract means the contract on the return value. Which in this case is
`void?`. So the complaint is that the procedure given in the first argument
is returning '11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of
`response/output`? The idea is that you write to the output-port directly
rather than returning a value to the caller. Insisting on void as a return
value imposes an extra measure of discipline, and sets an expectation.
The reason your 'not-working' dispatcher is not working is that
`write-bytes` does two things: it sends bytes to the output port, but then
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks
that's the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from `write-bytes`
and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can be
a more convenient way of making simple HTML or text responses.
[1]
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
[2]
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29
Post by André Matheus
Hi, starting a project of mine, I've setup a dispatch rule and a function
to return the response.
To make things simple, I've used response/output, with a lambda writing
to the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
I've setup some code that exposes the problem. Navigating to "/working"
and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof
header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
Alexander D. Knauth
2015-03-07 01:44:10 UTC
Permalink
For that the contract says
(output-port? . -> . void)
When it should say
(output-port? . -> . void?)
Curiously, the contract for `response` also requires an (-> output-port? void?) procedure [1]. The source code agrees. But the examples given in the docs don't include a (void) return value. Yet they do work. So perhaps there's a tiny bug where `response` is being more lenient than it's supposed to be.
[1] http://docs.racket-lang.org/web-server/http.html?q=response#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
I do sort of agree that the void? requirement is strange and unneeded. It’s usually only used to indicate that a function provided by some module returns #<void>, but callback functions are usually specified with any as the return value to allow precisely this sort of thing.
Post by André Matheus
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
The contract, by definition, is always right ;)
(output-port? . -> . void?)
(-> output-port? void?)
Note also that the error says the contract violation was "in the range of the 1st argument of" ... [giant contract follows]. That helps track down the error. The contract for the first argument is '(-> output-port? void?)'. This is a procedure contract. And "the range of" a procedure contract means the contract on the return value. Which in this case is `void?`. So the complaint is that the procedure given in the first argument is returning '11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of `response/output`? The idea is that you write to the output-port directly rather than returning a value to the caller. Insisting on void as a return value imposes an extra measure of discipline, and sets an expectation.
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks the contract, which demands void. (That's also why your error is '11': that's the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from `write-bytes` and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can be a more convenient way of making simple HTML or text responses.
[1] http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
[2] http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29
Hi, starting a project of mine, I've setup a dispatch rule and a function to return the response.
To make things simple, I've used response/output, with a lambda writing to the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
/usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
I've setup some code that exposes the problem. Navigating to "/working" and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
André Matheus
2015-03-07 02:09:11 UTC
Permalink
If I understood what Matthew said correctly, the point of the contract requiring void is to prevent
an error when someone uses a function returning a string rather than writing to the output port.

But in this case, response should require returning void too, right? What confused me more than
the error message and the contracts was that the same function worked when creating a response
but didn’t work when using response/output, but response/output simply creates a response with
default values, so my understanding was that the function should either work or fail on both.
Post by Alexis King
I do sort of agree that the void? requirement is strange and unneeded. It’s usually only used to indicate that a function provided by some module returns #<void>, but callback functions are usually specified with any as the return value to allow precisely this sort of thing.
Post by André Matheus
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
The contract, by definition, is always right ;)
(output-port? . -> . void?)
(-> output-port? void?)
Note also that the error says the contract violation was "in the range of the 1st argument of" ... [giant contract follows]. That helps track down the error. The contract for the first argument is '(-> output-port? void?)'. This is a procedure contract. And "the range of" a procedure contract means the contract on the return value. Which in this case is `void?`. So the complaint is that the procedure given in the first argument is returning '11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of `response/output`? The idea is that you write to the output-port directly rather than returning a value to the caller. Insisting on void as a return value imposes an extra measure of discipline, and sets an expectation.
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks the contract, which demands void. (That's also why your error is '11': that's the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from `write-bytes` and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can be a more convenient way of making simple HTML or text responses.
[1] http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29 <http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29>
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29 <http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29>
[2] http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29 <http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29>
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29 <http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29>
Hi, starting a project of mine, I've setup a dispatch rule and a function to return the response.
To make things simple, I've used response/output, with a lambda writing to the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
/usr/share/racket/collects/racket/contract/private/blame.rkt:143:0: raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
I've setup some code that exposes the problem. Navigating to "/working" and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users <http://lists.racket-lang.org/users>
____________________
http://lists.racket-lang.org/users <http://lists.racket-lang.org/users>
Jay McCarthy
2015-03-07 18:22:16 UTC
Permalink
I'm catching up on this thread.

The contracts should all be "void?" and it says "void" then it's
probably a typo and an error. "void" is a function that takes any
number of arguments and returns "void", which is not false, so "void"
is like an "any/c" contract, except that it is less efficient. (The
contract system will not put the same kind of wrapper when the
function can return anything.)

I'm loathe to fix this typo though, because I suspect that a lot of
code relies on the "void" behavior. If anything, I should change it to
have "any" so that it is more efficient and has the same errors.

Jay
Post by André Matheus
If I understood what Matthew said correctly, the point of the contract
requiring void is to prevent
an error when someone uses a function returning a string rather than writing
to the output port.
But in this case, response should require returning void too, right? What
confused me more than
the error message and the contracts was that the same function worked when
creating a response
but didn’t work when using response/output, but response/output simply
creates a response with
default values, so my understanding was that the function should either work
or fail on both.
I do sort of agree that the void? requirement is strange and unneeded. It’s
usually only used to indicate that a function provided by some module
returns #<void>, but callback functions are usually specified with any as
the return value to allow precisely this sort of thing.
Post by André Matheus
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
The contract, by definition, is always right ;)
In this case, `response/output` takes as its first argument a procedure that
accepts an output-port and returns void. [1] In contract-speak this is
(output-port? . -> . void?)
(-> output-port? void?)
Note also that the error says the contract violation was "in the range of
the 1st argument of" ... [giant contract follows]. That helps track down the
error. The contract for the first argument is '(-> output-port? void?)'.
This is a procedure contract. And "the range of" a procedure contract means
the contract on the return value. Which in this case is `void?`. So the
complaint is that the procedure given in the first argument is returning
'11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of
`response/output`? The idea is that you write to the output-port directly
rather than returning a value to the caller. Insisting on void as a return
value imposes an extra measure of discipline, and sets an expectation.
The reason your 'not-working' dispatcher is not working is that
`write-bytes` does two things: it sends bytes to the output port, but then
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks the
contract, which demands void. (That's also why your error is '11': that's
the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from `write-bytes`
and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can be a
more convenient way of making simple HTML or text responses.
[1]
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
[2]
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29
Post by André Matheus
Hi, starting a project of mine, I've setup a dispatch rule and a function
to return the response.
To make things simple, I've used response/output, with a lambda writing to
the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much about contracts.
I've setup some code that exposes the problem. Navigating to "/working"
and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof
header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
--
Jay McCarthy
http://jeapostrophe.github.io

"Wherefore, be not weary in well-doing,
for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
- D&C 64:33

____________________
Racke
Jay McCarthy
2015-03-07 18:23:15 UTC
Permalink
Oh and one more thing. The idea of the void? was to help catch
mistakes where someone thought they could return a xexpr or response
structure from these functions and have it returned.

Jay
Post by Jay McCarthy
I'm catching up on this thread.
The contracts should all be "void?" and it says "void" then it's
probably a typo and an error. "void" is a function that takes any
number of arguments and returns "void", which is not false, so "void"
is like an "any/c" contract, except that it is less efficient. (The
contract system will not put the same kind of wrapper when the
function can return anything.)
I'm loathe to fix this typo though, because I suspect that a lot of
code relies on the "void" behavior. If anything, I should change it to
have "any" so that it is more efficient and has the same errors.
Jay
Post by André Matheus
If I understood what Matthew said correctly, the point of the contract
requiring void is to prevent
an error when someone uses a function returning a string rather than writing
to the output port.
But in this case, response should require returning void too, right? What
confused me more than
the error message and the contracts was that the same function worked when
creating a response
but didn’t work when using response/output, but response/output simply
creates a response with
default values, so my understanding was that the function should either work
or fail on both.
I do sort of agree that the void? requirement is strange and unneeded. It’s
usually only used to indicate that a function provided by some module
returns #<void>, but callback functions are usually specified with any as
the return value to allow precisely this sort of thing.
Post by André Matheus
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much
about contracts.
The contract, by definition, is always right ;)
In this case, `response/output` takes as its first argument a procedure that
accepts an output-port and returns void. [1] In contract-speak this is
(output-port? . -> . void?)
(-> output-port? void?)
Note also that the error says the contract violation was "in the range of
the 1st argument of" ... [giant contract follows]. That helps track down the
error. The contract for the first argument is '(-> output-port? void?)'.
This is a procedure contract. And "the range of" a procedure contract means
the contract on the return value. Which in this case is `void?`. So the
complaint is that the procedure given in the first argument is returning
'11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of
`response/output`? The idea is that you write to the output-port directly
rather than returning a value to the caller. Insisting on void as a return
value imposes an extra measure of discipline, and sets an expectation.
The reason your 'not-working' dispatcher is not working is that
`write-bytes` does two things: it sends bytes to the output port, but then
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks the
contract, which demands void. (That's also why your error is '11': that's
the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from `write-bytes`
and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can be a
more convenient way of making simple HTML or text responses.
[1]
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
[2]
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29
Post by André Matheus
Hi, starting a project of mine, I've setup a dispatch rule and a function
to return the response.
To make things simple, I've used response/output, with a lambda writing to
the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then it worked.
I think maybe the contract is wrong but frankly I don't understand much
about contracts.
I've setup some code that exposes the problem. Navigating to "/working"
and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?) (listof
header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
--
Jay McCarthy
http://jeapostrophe.github.io
"Wherefore, be not weary in well-doing,
for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
- D&C 64:33
--
Jay McCarthy
http://jeapostrophe.github.io

"Wherefore, be not weary in well-doing,
for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
- D&C 64:33

____________________
Racket Users
Matthew Butterick
2015-03-07 20:31:05 UTC
Permalink
Ah yes, please forgive my error. I was wrong when I said "the contract for
`response` also requires an (-> output-port? void?) procedure". I misread
it.

The moral of the story, however, remains the same — contracts are not final
because they're infallible; they're infallible because they're final.
Post by Jay McCarthy
Oh and one more thing. The idea of the void? was to help catch
mistakes where someone thought they could return a xexpr or response
structure from these functions and have it returned.
Jay
Post by Jay McCarthy
I'm catching up on this thread.
The contracts should all be "void?" and it says "void" then it's
probably a typo and an error. "void" is a function that takes any
number of arguments and returns "void", which is not false, so "void"
is like an "any/c" contract, except that it is less efficient. (The
contract system will not put the same kind of wrapper when the
function can return anything.)
I'm loathe to fix this typo though, because I suspect that a lot of
code relies on the "void" behavior. If anything, I should change it to
have "any" so that it is more efficient and has the same errors.
Jay
Post by André Matheus
If I understood what Matthew said correctly, the point of the contract
requiring void is to prevent
an error when someone uses a function returning a string rather than
writing
Post by Jay McCarthy
Post by André Matheus
to the output port.
But in this case, response should require returning void too, right?
What
Post by Jay McCarthy
Post by André Matheus
confused me more than
the error message and the contracts was that the same function worked
when
Post by Jay McCarthy
Post by André Matheus
creating a response
but didn’t work when using response/output, but response/output simply
creates a response with
default values, so my understanding was that the function should either
work
Post by Jay McCarthy
Post by André Matheus
or fail on both.
I do sort of agree that the void? requirement is strange and unneeded.
It’s
Post by Jay McCarthy
Post by André Matheus
usually only used to indicate that a function provided by some module
returns #<void>, but callback functions are usually specified with any
as
Post by Jay McCarthy
Post by André Matheus
the return value to allow precisely this sort of thing.
Post by André Matheus
From the error message, I changed the lambda to return (void) and then
it
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
worked.
I think maybe the contract is wrong but frankly I don't understand much
about contracts.
The contract, by definition, is always right ;)
In this case, `response/output` takes as its first argument a procedure
that
Post by Jay McCarthy
Post by André Matheus
accepts an output-port and returns void. [1] In contract-speak this is
(output-port? . -> . void?)
but it appears in error messages, like the one above, with the
equivalent
Post by Jay McCarthy
Post by André Matheus
(-> output-port? void?)
Note also that the error says the contract violation was "in the range
of
Post by Jay McCarthy
Post by André Matheus
the 1st argument of" ... [giant contract follows]. That helps track
down the
Post by Jay McCarthy
Post by André Matheus
error. The contract for the first argument is '(-> output-port? void?)'.
This is a procedure contract. And "the range of" a procedure contract
means
Post by Jay McCarthy
Post by André Matheus
the contract on the return value. Which in this case is `void?`. So the
complaint is that the procedure given in the first argument is returning
'11' when it should be returning void.
Why is (-> output-port? void?) the contract for the first arg of
`response/output`? The idea is that you write to the output-port
directly
Post by Jay McCarthy
Post by André Matheus
rather than returning a value to the caller. Insisting on void as a
return
Post by Jay McCarthy
Post by André Matheus
value imposes an extra measure of discipline, and sets an expectation.
The reason your 'not-working' dispatcher is not working is that
`write-bytes` does two things: it sends bytes to the output port, but
then
Post by Jay McCarthy
Post by André Matheus
(λ (op) (write-bytes #"Hello world" op))
is defective because it returns the number of bytes. Meaning, it breaks
the
that's
Post by Jay McCarthy
Post by André Matheus
the number of bytes in "Hello world").
(λ (op) (write-bytes #"Hello world" op) (void))
Meets the contract because it ignores the return value from
`write-bytes`
Post by Jay McCarthy
Post by André Matheus
and returns (void) instead.
You should repeat this technique whenever you use `response/output`.
You can also look into `response/full` and `response/xexpr`, which can
be a
Post by Jay McCarthy
Post by André Matheus
more convenient way of making simple HTML or text responses.
[1]
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%2Foutput%29%29
Post by Jay McCarthy
Post by André Matheus
which cross-references
http://docs.racket-lang.org/web-server/http.html?q=response%2Foutput#%28def._%28%28lib._web-server%2Fhttp%2Fresponse-structs..rkt%29._response%29%29
Post by Jay McCarthy
Post by André Matheus
[2]
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-bytes%29%29
Post by Jay McCarthy
Post by André Matheus
which cross-references
http://docs.racket-lang.org/reference/Byte_and_String_Output.html?q=write-bytes#%28def._%28%28quote._~23~25kernel%29._write-string%29%29
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
Hi, starting a project of mine, I've setup a dispatch rule and a
function
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
to return the response.
To make things simple, I've used response/output, with a lambda
writing to
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
the output-port.
response/output: contract violation
expected: void?
given: 11
in: the range of
the 1st argument of
(->*
((-> output-port? void?))
(#:code
number?
#:headers
(listof header?)
#:message
bytes?
#:mime-type
(or/c bytes? #f)
#:seconds
number?)
response?)
<pkgs>/web-server-lib/web-server/http/response-structs.rkt
blaming: /home/amatheus/Dropbox/focus/todagendas/teste.rkt
(assuming the contract is correct)
at: <pkgs>/web-server-lib/web-server/http/response-structs.rkt:41.2
raise-blame-error16
/usr/share/racket/pkgs/web-server-lib/web-server/http/response.rkt:115:12
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
So I've tried to use a response, with the same lambda, and it worked.
From the error message, I changed the lambda to return (void) and then
it
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
worked.
I think maybe the contract is wrong but frankly I don't understand much
about contracts.
I've setup some code that exposes the problem. Navigating to "/working"
and "/fixed" works
fine; navigating to "/not-working" exposes the problem.
#lang racket
(require web-server/dispatch
web-server/servlet-env
net/url
web-server/http/request-structs
web-server/http/response-structs)
(define (not-working req)
(response/output (λ (op) (write-bytes #"Hello world" op))))
(define (working req)
(response
301 #"OK"
(current-seconds) TEXT/HTML-MIME-TYPE
empty
(λ (op) (write-bytes #"Hello world" op))))
(define (fixed req)
(response/output (λ (op) (write-bytes #"Hello world" op) (void))))
(define (url->request u)
(make-request #"GET" (string->url u) empty
(delay empty) #f "1.2.3.4" 80 "4.3.2.1"))
(define-values (agenda-dispatch agenda-url)
(dispatch-rules
[("working") working]
[("not-working") not-working]
[("fixed") fixed]))
(define (main)
(serve/servlet agenda-dispatch
#:servlet-regexp #rx""
#:servlet-path ""))
(module+ main
(main))
(provide/contract
[struct response
([code number?]
[message bytes?]
[seconds number?]
[mime (or/c false/c bytes?)]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/full (-> number? bytes? number? (or/c false/c bytes?)
(listof
Post by Jay McCarthy
Post by André Matheus
Post by André Matheus
header?) (listof bytes?) response?)]
[response/output (->* ((-> output-port? void?))
(#:code number?
#:message bytes?
#:seconds number?
#:mime-type (or/c bytes? #f)
#:headers (listof header?))
response?)]
[TEXT/HTML-MIME-TYPE bytes?])
Is the contract wrong or am I doing something weird?
Thanks,
André
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
____________________
http://lists.racket-lang.org/users
--
Jay McCarthy
http://jeapostrophe.github.io
"Wherefore, be not weary in well-doing,
for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
- D&C 64:33
--
Jay McCarthy
http://jeapostrophe.github.io
"Wherefore, be not weary in well-doing,
for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
- D&C 64:33
Loading...