Compare commits

...

1 Commits

Author SHA1 Message Date
Jef Roosens 8099acff01 refactor(web): some small refactors 2022-12-29 23:38:33 +01:00
3 changed files with 28 additions and 82 deletions

View File

@ -6,7 +6,7 @@ import os
// reader_to_writer tries to consume the entire reader & write it to the writer. // reader_to_writer tries to consume the entire reader & write it to the writer.
pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ! { pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ! {
mut buf := []u8{len: 10 * 1024} mut buf := []u8{len: 8192}
for { for {
bytes_read := reader.read(mut buf) or { break } bytes_read := reader.read(mut buf) or { break }
@ -27,7 +27,7 @@ pub fn reader_to_file(mut reader io.BufferedReader, length int, path string) ! {
file.close() file.close()
} }
mut buf := []u8{len: reader_buf_size} mut buf := []u8{len: 8192}
mut bytes_left := length mut bytes_left := length
// Repeat as long as the stream still has data // Repeat as long as the stream still has data
@ -47,49 +47,3 @@ pub fn reader_to_file(mut reader io.BufferedReader, length int, path string) ! {
} }
} }
} }
// match_array_in_array<T> returns how many elements of a2 overlap with a1. For
// example, if a1 = "abcd" & a2 = "cd", the result will be 2. If the match is
// not at the end of a1, the result is 0.
pub fn match_array_in_array<T>(a1 []T, a2 []T) int {
mut i := 0
mut match_len := 0
for i + match_len < a1.len {
if a1[i + match_len] == a2[match_len] {
match_len += 1
} else {
i += match_len + 1
match_len = 0
}
}
return match_len
}
// read_until_separator consumes an io.Reader until it encounters some
// separator array. The data read is stored inside the provided res array.
pub fn read_until_separator(mut reader io.Reader, mut res []u8, sep []u8) ! {
mut buf := []u8{len: sep.len}
for {
c := reader.read(mut buf)!
res << buf[..c]
match_len := match_array_in_array(buf[..c], sep)
if match_len == sep.len {
break
}
if match_len > 0 {
match_left := sep.len - match_len
c2 := reader.read(mut buf[..match_left])!
res << buf[..c2]
if buf[..c2] == sep[match_len..] {
break
}
}
}
}

View File

@ -3,10 +3,7 @@ module util
import os import os
import crypto.sha256 import crypto.sha256
const ( const prefixes = ['B', 'KB', 'MB', 'GB']
reader_buf_size = 1_000_000
prefixes = ['B', 'KB', 'MB', 'GB']
)
// Dummy struct to work around the fact that you can only share structs, maps & // Dummy struct to work around the fact that you can only share structs, maps &
// arrays // arrays
@ -24,18 +21,13 @@ pub fn exit_with_message(code int, msg string) {
// hash_file returns the sha256 hash of a given file // hash_file returns the sha256 hash of a given file
pub fn hash_file(path &string) !string { pub fn hash_file(path &string) !string {
file := os.open(path) or { return error('Failed to open file.') } file := os.open(path)!
mut sha256sum := sha256.new() mut sha256sum := sha256.new()
mut buf := []u8{len: 8192}
buf_size := int(1_000_000) for !file.eof() {
mut buf := []u8{len: buf_size} bytes_read := file.read(mut buf)!
mut bytes_left := os.file_size(path)
for bytes_left > 0 {
// TODO check if just breaking here is safe
bytes_read := file.read(mut buf) or { return error('Failed to read from file.') }
bytes_left -= u64(bytes_read)
// This function never actually fails, but returns an option to follow // This function never actually fails, but returns an option to follow
// the Writer interface. // the Writer interface.

View File

@ -75,7 +75,7 @@ fn (mut ctx Context) send_string(s string) ! {
// to the TCP connection socket. Internally, a 10KB buffer is used, to avoid // to the TCP connection socket. Internally, a 10KB buffer is used, to avoid
// having to store all bytes in memory at once. // having to store all bytes in memory at once.
fn (mut ctx Context) send_reader(mut reader io.Reader, size u64) ! { fn (mut ctx Context) send_reader(mut reader io.Reader, size u64) ! {
mut buf := []u8{len: 10_000} mut buf := []u8{len: 8192}
mut bytes_left := size mut bytes_left := size
// Repeat as long as the stream still has data // Repeat as long as the stream still has data
@ -156,15 +156,11 @@ pub fn (mut ctx Context) json<T>(status http.Status, j T) Result {
return Result{} return Result{}
} }
// file Response HTTP_OK with file as payload // File serves the given file path by streaming its content to the client.
// This function manually implements responses because it needs to stream the file contents
pub fn (mut ctx Context) file(f_path string) Result { pub fn (mut ctx Context) file(f_path string) Result {
// If the file doesn't exist, just respond with a 404 // If the file doesn't exist, just respond with a 404
if !os.is_file(f_path) { if !os.is_file(f_path) {
ctx.status = .not_found return ctx.status(.not_found)
ctx.send()
return Result{}
} }
ctx.header.add(.accept_ranges, 'bytes') ctx.header.add(.accept_ranges, 'bytes')
@ -180,9 +176,11 @@ pub fn (mut ctx Context) file(f_path string) Result {
} }
mut file := os.open(f_path) or { mut file := os.open(f_path) or {
eprintln(err.msg()) lock ctx.logger {
ctx.server_error(500) ctx.logger.error('Error in file(): $err.msg()')
return Result{} }
return ctx.status(.internal_server_error)
} }
defer { defer {
@ -217,8 +215,11 @@ pub fn (mut ctx Context) file(f_path string) Result {
// Move cursor to start of data to read // Move cursor to start of data to read
file.seek(start, .start) or { file.seek(start, .start) or {
ctx.server_error(500) lock ctx.logger {
return Result{} ctx.logger.error('Error in file(): $err.msg()')
}
return ctx.status(.internal_server_error)
} }
length := end - u64(start) + 1 length := end - u64(start) + 1
@ -242,13 +243,6 @@ pub fn (mut ctx Context) status(status http.Status) Result {
return Result{} return Result{}
} }
// server_error Response a server error
pub fn (mut ctx Context) server_error(ecode int) Result {
ctx.send_custom_response(http_500) or {}
return Result{}
}
// redirect Redirect to an url // redirect Redirect to an url
pub fn (mut ctx Context) redirect(url string) Result { pub fn (mut ctx Context) redirect(url string) Result {
mut resp := http_302 mut resp := http_302
@ -335,8 +329,11 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T, routes map[string]Route) {
head := http.parse_request_head(mut reader) or { head := http.parse_request_head(mut reader) or {
// Prevents errors from being thrown when BufferedReader is empty // Prevents errors from being thrown when BufferedReader is empty
if '$err' != 'none' { if '$err' != 'none' {
eprintln('error parsing request head: $err') lock app.logger {
app.logger.error('error parsing request head: $err')
} }
}
return return
} }
@ -357,7 +354,10 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T, routes map[string]Route) {
// URL Parse // URL Parse
url := urllib.parse(head.url) or { url := urllib.parse(head.url) or {
eprintln('error parsing path: $err') lock app.logger {
app.logger.error('error parsing path: $err')
}
return return
} }