Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Jef Roosens | 8099acff01 |
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue