nitcorn: use `bytelen` instead of `length` when setting `Content-Length` header
[nit.git] / lib / nitcorn / http_response.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Frederic Sevillano
4 # Copyright 2013 Jean-Philippe Caissy <jpcaissy@piji.ca>
5 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18
19 # Provides the `HttpResponse` class and `http_status_codes`
20 module http_response
21
22 # A response to send over HTTP
23 class HttpResponse
24
25 # HTTP protocol version
26 var http_version = "HTTP/1.0" is writable
27
28 # Status code of this response (200, 404, etc.)
29 var status_code: Int is writable
30
31 # Return the message associated to `status_code`
32 fun status_message: nullable String do return http_status_codes[status_code]
33
34 # Headers of this response as a `Map`
35 var header = new HashMap[String, String]
36
37 # Body of this response
38 var body = "" is writable
39
40 # Finalize this response before sending it over HTTP
41 fun finalize
42 do
43 # Set the content length if not already set
44 if not header.keys.has("Content-Length") then
45 header["Content-Length"] = body.bytelen.to_s
46 end
47
48 # Set server ID
49 if not header.keys.has("Server") then header["Server"] = "unitcorn"
50 end
51
52 # Get this reponse as a string according to HTTP protocol
53 redef fun to_s
54 do
55 finalize
56
57 var buf = new FlatBuffer
58 buf.append("{http_version} {status_code} {status_message or else ""}\r\n")
59 for key, value in header do
60 buf.append("{key}: {value}\r\n")
61 end
62 buf.append("\r\n{body}")
63 return buf.to_s
64 end
65 end
66
67 # Helper class to associate HTTP status code to their message
68 #
69 # You probably want the default instance available as the top-level method
70 # `http_status_codes`.
71 class HttpStatusCodes
72
73 # All know code and their message
74 var codes = new HashMap[Int, String]
75
76 protected init do insert_status_codes
77
78 # Get the message associated to the status `code`, return `null` in unknown
79 fun [](code: Int): nullable String
80 do
81 if codes.keys.has(code) then
82 return codes[code]
83 else return null
84 end
85
86 private fun insert_status_codes
87 do
88 codes[100] = "Continue"
89 codes[101] = "Switching Protocols"
90 codes[200] = "OK"
91 codes[201] = "Created"
92 codes[202] = "Accepted"
93 codes[203] = "Non-Authoritative Information"
94 codes[204] = "No Content"
95 codes[205] = "Reset Content"
96 codes[206] = "Partial Content"
97 codes[300] = "Multiple Choices"
98 codes[301] = "Moved Permanently"
99 codes[302] = "Found"
100 codes[303] = "See Other"
101 codes[304] = "Not Modified"
102 codes[305] = "Use Proxy"
103 codes[307] = "Temporary Redirect"
104 codes[400] = "Bad Request"
105 codes[401] = "Unauthorized"
106 codes[402] = "Payment Requred"
107 codes[403] = "Forbidden"
108 codes[404] = "Not Found"
109 codes[405] = "Method Not Allowed"
110 codes[406] = "Not Acceptable"
111 codes[407] = "Proxy Authentication Required"
112 codes[408] = "Request Timeout"
113 codes[409] = "Conflict"
114 codes[410] = "Gone"
115 codes[411] = "Length Required"
116 codes[412] = "Precondition Failed"
117 codes[413] = "Request Entity Too Large"
118 codes[414] = "Request-URI Too Long"
119 codes[415] = "Unsupported Media Type"
120 codes[416] = "Requested Range Not Satisfiable"
121 codes[417] = "Expectation Failed"
122 codes[500] = "Internal Server Error"
123 codes[501] = "Not Implemented"
124 codes[502] = "Bad Gateway"
125 codes[503] = "Service Unavailable"
126 codes[504] = "Gateway Timeout"
127 codes[505] = "HTTP Version Not Supported"
128 end
129 end
130
131 # Get the default instance of `HttpStatusCodes`
132 fun http_status_codes: HttpStatusCodes do return once new HttpStatusCodes