vweb: use http.Response constants instead of strings (#10730)
							parent
							
								
									cb14e42af8
								
							
						
					
					
						commit
						44e78a6301
					
				|  | @ -22,10 +22,15 @@ fn (mut resp Response) free() { | |||
| // Formats resp to bytes suitable for HTTP response transmission
 | ||||
| pub fn (resp Response) bytes() []byte { | ||||
| 	// TODO: build []byte directly; this uses two allocations
 | ||||
| 	return resp.bytestr().bytes() | ||||
| } | ||||
| 
 | ||||
| // Formats resp to a string suitable for HTTP response transmission
 | ||||
| pub fn (resp Response) bytestr() string { | ||||
| 	// TODO: cookies
 | ||||
| 	return ('$resp.version $resp.status_code ${status_from_int(resp.status_code).str()}\r\n' + '${resp.header.render( | ||||
| 		version: resp.version | ||||
| 	)}\r\n' + '$resp.text').bytes() | ||||
| 	)}\r\n' + '$resp.text') | ||||
| } | ||||
| 
 | ||||
| // Parse a raw HTTP response into a Response object
 | ||||
|  |  | |||
|  | @ -12,15 +12,59 @@ import strings | |||
| import time | ||||
| 
 | ||||
| pub const ( | ||||
| 	methods_with_form       = [http.Method.post, .put, .patch] | ||||
| 	header_server           = 'Server: VWeb\r\n' | ||||
| 	header_connection_close = 'Connection: close\r\n' | ||||
| 	headers_close           = '$header_server$header_connection_close\r\n' | ||||
| 	// TODO: use http.response structs
 | ||||
| 	http_400                = 'HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nContent-Length: 15\r\n${headers_close}400 Bad Request' | ||||
| 	http_404                = 'HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: 13\r\n${headers_close}404 Not Found' | ||||
| 	http_500                = 'HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n${headers_close}500 Internal Server Error' | ||||
| 	mime_types              = map{ | ||||
| 	methods_with_form = [http.Method.post, .put, .patch] | ||||
| 	http_400          = http.Response{ | ||||
| 		version: .v1_1 | ||||
| 		status_code: 400 | ||||
| 		text: '400 Bad Request' | ||||
| 		header: fn () http.Header { | ||||
| 			mut h := http.new_header() | ||||
| 			h.add(.content_type, 'text/plain') | ||||
| 			h.add(.content_length, '15') | ||||
| 			close := headers_close() | ||||
| 			for k in close.keys() { | ||||
| 				for v in close.custom_values(k) { | ||||
| 					h.add_custom(k, v) or {} | ||||
| 				} | ||||
| 			} | ||||
| 			return h | ||||
| 		}() | ||||
| 	} | ||||
| 	http_404 = http.Response{ | ||||
| 		version: .v1_1 | ||||
| 		status_code: 404 | ||||
| 		text: '404 Not Found' | ||||
| 		header: fn () http.Header { | ||||
| 			mut h := http.new_header() | ||||
| 			h.add(.content_type, 'text/plain') | ||||
| 			h.add(.content_length, '13') | ||||
| 			close := headers_close() | ||||
| 			for k in close.keys() { | ||||
| 				for v in close.custom_values(k) { | ||||
| 					h.add_custom(k, v) or {} | ||||
| 				} | ||||
| 			} | ||||
| 			return h | ||||
| 		}() | ||||
| 	} | ||||
| 	http_500 = http.Response{ | ||||
| 		version: .v1_1 | ||||
| 		status_code: 500 | ||||
| 		text: '500 Internal Server Error' | ||||
| 		header: fn () http.Header { | ||||
| 			mut h := http.new_header() | ||||
| 			h.add(.content_type, 'text/plain') | ||||
| 			h.add(.content_length, '25') | ||||
| 			close := headers_close() | ||||
| 			for k in close.keys() { | ||||
| 				for v in close.custom_values(k) { | ||||
| 					h.add_custom(k, v) or {} | ||||
| 				} | ||||
| 			} | ||||
| 			return h | ||||
| 		}() | ||||
| 	} | ||||
| 	mime_types = map{ | ||||
| 		'.css':  'text/css; charset=utf-8' | ||||
| 		'.gif':  'image/gif' | ||||
| 		'.htm':  'text/html; charset=utf-8' | ||||
|  | @ -117,7 +161,8 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo | |||
| 	} | ||||
| 	sb.write_string(ctx.headers) | ||||
| 	sb.write_string('\r\n') | ||||
| 	sb.write_string(vweb.headers_close) | ||||
| 	sb.write_string(headers_close().str()) | ||||
| 	sb.write_string('\r\n') | ||||
| 	if ctx.chunked_transfer { | ||||
| 		mut i := 0 | ||||
| 		mut len := res.len | ||||
|  | @ -181,7 +226,7 @@ pub fn (mut ctx Context) server_error(ecode int) Result { | |||
| 	if ctx.done { | ||||
| 		return Result{} | ||||
| 	} | ||||
| 	send_string(mut ctx.conn, vweb.http_500) or {} | ||||
| 	send_string(mut ctx.conn, vweb.http_500.bytestr()) or {} | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
|  | @ -191,7 +236,7 @@ pub fn (mut ctx Context) redirect(url string) Result { | |||
| 		return Result{} | ||||
| 	} | ||||
| 	ctx.done = true | ||||
| 	send_string(mut ctx.conn, 'HTTP/1.1 302 Found\r\nLocation: $url$ctx.headers\r\n$vweb.headers_close') or { | ||||
| 	send_string(mut ctx.conn, 'HTTP/1.1 302 Found\r\nLocation: $url$ctx.headers\r\n$headers_close().str()\r\n') or { | ||||
| 		return Result{} | ||||
| 	} | ||||
| 	return Result{} | ||||
|  | @ -203,7 +248,7 @@ pub fn (mut ctx Context) not_found() Result { | |||
| 		return Result{} | ||||
| 	} | ||||
| 	ctx.done = true | ||||
| 	send_string(mut ctx.conn, vweb.http_404) or {} | ||||
| 	send_string(mut ctx.conn, vweb.http_404.bytestr()) or {} | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
|  | @ -378,7 +423,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) { | |||
| 		if 'multipart/form-data' in ct { | ||||
| 			boundary := ct.filter(it.starts_with('boundary=')) | ||||
| 			if boundary.len != 1 { | ||||
| 				send_string(mut conn, vweb.http_400) or {} | ||||
| 				send_string(mut conn, vweb.http_400.bytestr()) or {} | ||||
| 				return | ||||
| 			} | ||||
| 			form, files := parse_multipart_form(req.data, boundary[0][9..]) | ||||
|  | @ -457,7 +502,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) { | |||
| 		} | ||||
| 	} | ||||
| 	// site not found
 | ||||
| 	send_string(mut conn, vweb.http_404) or {} | ||||
| 	send_string(mut conn, vweb.http_404.bytestr()) or {} | ||||
| } | ||||
| 
 | ||||
| fn route_matches(url_words []string, route_words []string) ?[]string { | ||||
|  | @ -553,7 +598,7 @@ fn serve_if_static<T>(mut app T, url urllib.URL) bool { | |||
| 		return false | ||||
| 	} | ||||
| 	data := os.read_file(static_file) or { | ||||
| 		send_string(mut app.conn, vweb.http_404) or {} | ||||
| 		send_string(mut app.conn, vweb.http_404.bytestr()) or {} | ||||
| 		return true | ||||
| 	} | ||||
| 	app.send_response_to_client(mime_type, data) | ||||
|  | @ -662,3 +707,9 @@ pub type RawHtml = string | |||
| fn send_string(mut conn net.TcpConn, s string) ? { | ||||
| 	conn.write(s.bytes()) ? | ||||
| } | ||||
| 
 | ||||
| fn headers_close() http.Header { | ||||
| 	mut h := http.new_header(key: .connection, value: 'close') | ||||
| 	h.add_custom('Server', 'VWeb') or {} | ||||
| 	return h | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue