vweb: run vfmt, add it to `v test-cleancode`

pull/7606/head
Delyan Angelov 2020-12-27 11:38:12 +02:00
parent 1b9d514275
commit d563261e58
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
8 changed files with 94 additions and 181 deletions

View File

@ -66,6 +66,7 @@ const (
'vlib/semver/', 'vlib/semver/',
'vlib/strings/', 'vlib/strings/',
'vlib/time/', 'vlib/time/',
'vlib/vweb/',
] ]
) )

View File

@ -8,8 +8,6 @@ const (
known_failing_exceptions = [ known_failing_exceptions = [
'vlib/crypto/aes/const.v', 'vlib/crypto/aes/const.v',
/* multiple narrow columns of []string turned to 1 long single column, otherwise works */ /* multiple narrow columns of []string turned to 1 long single column, otherwise works */
'vlib/vweb/vweb.v',
/* $for method in T.methods { => $for method in T(methods) { , `return // xx` => parse expr error */
'vlib/v/gen/js/tests/life.v', 'vlib/v/gen/js/tests/life.v',
/* error: unexpected `,`, expecting ), on JS.setInterval(fn () { show(game) game = step(game) }, 500) */ /* error: unexpected `,`, expecting ), on JS.setInterval(fn () { show(game) game = step(game) }, 500) */
'vlib/builtin/js/builtin.v', 'vlib/builtin/js/builtin.v',
@ -17,11 +15,10 @@ const (
'vlib/builtin/js/jsfns_node.js.v', 'vlib/builtin/js/jsfns_node.js.v',
'vlib/builtin/js/jsfns.js.v', 'vlib/builtin/js/jsfns.js.v',
'vlib/builtin/js/jsfns_browser.js.v', 'vlib/builtin/js/jsfns_browser.js.v',
'vlib/builtin/bare/linuxsys_bare.v',
/* error: expr(): bad token `asm`, on `asm {}` */ /* error: expr(): bad token `asm`, on `asm {}` */
'vlib/picoev/picoev.v', 'vlib/builtin/bare/linuxsys_bare.v',
/* the fn args are removed, then `cb fn (picohttpparser.Request, mut picohttpparser.Response)` can not be reparsed */ /* the fn args are removed, then `cb fn (picohttpparser.Request, mut picohttpparser.Response)` can not be reparsed */
'vlib/os/os.v' /* os.v - `a := [ c'/bin/sh', c'-c', byteptr(cmd.str), 0 ]` */, 'vlib/picoev/picoev.v',
] ]
) )

View File

@ -77,16 +77,12 @@ fn (am AssetManager) combine(asset_type string, to_file bool) string {
if to_file { if to_file {
return out_file return out_file
} }
cached := os.read_file(out_file) or { cached := os.read_file(out_file) or { return '' }
return ''
}
return cached return cached
} }
// rebuild // rebuild
for asset in am.get_assets(asset_type) { for asset in am.get_assets(asset_type) {
data := os.read_file(asset.file_path) or { data := os.read_file(asset.file_path) or { return '' }
return ''
}
out += data out += data
} }
if am.minify { if am.minify {
@ -100,13 +96,9 @@ fn (am AssetManager) combine(asset_type string, to_file bool) string {
return out return out
} }
if !os.is_dir(am.cache_dir) { if !os.is_dir(am.cache_dir) {
os.mkdir(am.cache_dir) or { os.mkdir(am.cache_dir) or { panic(err) }
panic(err)
}
}
mut file := os.create(out_file) or {
panic(err)
} }
mut file := os.create(out_file) or { panic(err) }
file.write(out.bytes()) file.write(out.bytes())
file.close() file.close()
return out_file return out_file

View File

@ -20,15 +20,12 @@ fn cache_dir(test_name string) string {
fn get_test_file_path(file string) string { fn get_test_file_path(file string) string {
path := os.join_path(base_cache_dir(), file) path := os.join_path(base_cache_dir(), file)
if !os.is_dir(base_cache_dir()) {
if ! os.is_dir(base_cache_dir()) {
os.mkdir_all(base_cache_dir()) os.mkdir_all(base_cache_dir())
} }
if !os.exists(path) {
if ! os.exists(path) {
os.write_file(path, get_test_file_contents(file)) os.write_file(path, get_test_file_contents(file))
} }
return path return path
} }
@ -40,7 +37,6 @@ fn get_test_file_contents(file string) string {
'test2.css' { '.two {\n\tcolor: #996633;\n}\n' } 'test2.css' { '.two {\n\tcolor: #996633;\n}\n' }
else { 'wibble\n' } else { 'wibble\n' }
} }
return contents return contents
} }
@ -80,23 +76,19 @@ fn test_combine_css() {
mut am := assets.new_manager() mut am := assets.new_manager()
am.cache_dir = cache_dir('test_combine_css') am.cache_dir = cache_dir('test_combine_css')
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
am.add_css(get_test_file_path('test1.css')) am.add_css(get_test_file_path('test1.css'))
am.add_css(get_test_file_path('test2.css')) am.add_css(get_test_file_path('test2.css'))
// TODO: How do I test non-minified, is there a "here doc" format that keeps formatting? // TODO: How do I test non-minified, is there a "here doc" format that keeps formatting?
am.minify = true am.minify = true
expected := '.one { color: #336699; } .two { color: #996633; } ' expected := '.one { color: #336699; } .two { color: #996633; } '
actual := am.combine_css(false) actual := am.combine_css(false)
assert actual == expected assert actual == expected
assert actual.contains(expected) assert actual.contains(expected)
// Test cache path doesn't change when input files and minify setting do not. // Test cache path doesn't change when input files and minify setting do not.
path1 := am.combine_css(true) path1 := am.combine_css(true)
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
path2 := am.combine_css(true) path2 := am.combine_css(true)
assert path1 == path2 assert path1 == path2
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
} }
@ -104,10 +96,8 @@ fn test_combine_js() {
mut am := assets.new_manager() mut am := assets.new_manager()
am.cache_dir = cache_dir('test_combine_js') am.cache_dir = cache_dir('test_combine_js')
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
am.add_js(get_test_file_path('test1.js')) am.add_js(get_test_file_path('test1.js'))
am.add_js(get_test_file_path('test2.js')) am.add_js(get_test_file_path('test2.js'))
expected1 := '{"one": 1}' expected1 := '{"one": 1}'
expected2 := '{"two": 2}' expected2 := '{"two": 2}'
expected := expected1 + '\n' + expected2 + '\n' expected := expected1 + '\n' + expected2 + '\n'
@ -116,20 +106,17 @@ fn test_combine_js() {
assert actual.contains(expected) assert actual.contains(expected)
assert actual.contains(expected1) assert actual.contains(expected1)
assert actual.contains(expected2) assert actual.contains(expected2)
am.minify = true am.minify = true
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
expected3 := expected1 + ' ' + expected2 + ' ' expected3 := expected1 + ' ' + expected2 + ' '
actual2 := am.combine_js(false) actual2 := am.combine_js(false)
assert actual2 == expected3 assert actual2 == expected3
assert actual2.contains(expected3) assert actual2.contains(expected3)
// Test cache path doesn't change when input files and minify setting do not. // Test cache path doesn't change when input files and minify setting do not.
path1 := am.combine_js(true) path1 := am.combine_js(true)
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
path2 := am.combine_js(true) path2 := am.combine_js(true)
assert path1 == path2 assert path1 == path2
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
} }
@ -141,29 +128,24 @@ fn test_include_css() {
actual := am.include_css(false) actual := am.include_css(false)
assert actual == expected assert actual == expected
assert actual.contains(expected) assert actual.contains(expected)
// Two lines of output. // Two lines of output.
file2 := get_test_file_path('test2.css') file2 := get_test_file_path('test2.css')
am.add_css(file2) am.add_css(file2)
am.cache_dir = cache_dir('test_include_css') am.cache_dir = cache_dir('test_include_css')
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
expected2 := expected + '<link rel="stylesheet" href="$file2">\n' expected2 := expected + '<link rel="stylesheet" href="$file2">\n'
actual2 := am.include_css(false) actual2 := am.include_css(false)
assert actual2 == expected2 assert actual2 == expected2
assert actual2.contains(expected2) assert actual2.contains(expected2)
// Combined output. // Combined output.
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
actual3 := am.include_css(true) actual3 := am.include_css(true)
assert actual3.contains(expected2) == false assert actual3.contains(expected2) == false
assert actual3.starts_with('<link rel="stylesheet" href="${am.cache_dir}/') == true assert actual3.starts_with('<link rel="stylesheet" href="$am.cache_dir/') == true
// Test cache path doesn't change when input files and minify setting do not. // Test cache path doesn't change when input files and minify setting do not.
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
actual4 := am.include_css(true) actual4 := am.include_css(true)
assert actual4 == actual3 assert actual4 == actual3
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
} }
@ -175,28 +157,23 @@ fn test_include_js() {
actual := am.include_js(false) actual := am.include_js(false)
assert actual == expected assert actual == expected
assert actual.contains(expected) assert actual.contains(expected)
// Two lines of output. // Two lines of output.
file2 := get_test_file_path('test2.js') file2 := get_test_file_path('test2.js')
am.add_js(file2) am.add_js(file2)
am.cache_dir = cache_dir('test_include_js') am.cache_dir = cache_dir('test_include_js')
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
expected2 := expected + '<script type="text/javascript" src="$file2"></script>\n' expected2 := expected + '<script type="text/javascript" src="$file2"></script>\n'
actual2 := am.include_js(false) actual2 := am.include_js(false)
assert actual2 == expected2 assert actual2 == expected2
assert actual2.contains(expected2) assert actual2.contains(expected2)
// Combined output. // Combined output.
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
actual3 := am.include_js(true) actual3 := am.include_js(true)
assert actual3.contains(expected2) == false assert actual3.contains(expected2) == false
assert actual3.starts_with('<script type="text/javascript" src="${am.cache_dir}/') assert actual3.starts_with('<script type="text/javascript" src="$am.cache_dir/')
// Test cache path doesn't change when input files and minify setting do not. // Test cache path doesn't change when input files and minify setting do not.
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
actual4 := am.include_js(true) actual4 := am.include_js(true)
assert actual4 == actual3 assert actual4 == actual3
clean_cache_dir(am.cache_dir) clean_cache_dir(am.cache_dir)
} }

View File

@ -64,9 +64,7 @@ fn test_a_simple_tcp_client_can_connect_to_the_vweb_server() {
} }
fn test_a_simple_tcp_client_simple_route() { fn test_a_simple_tcp_client_simple_route() {
received := simple_tcp_client({ received := simple_tcp_client(path: '/simple') or {
path: '/simple'
}) or {
assert err == '' assert err == ''
return return
} }
@ -77,9 +75,7 @@ fn test_a_simple_tcp_client_simple_route() {
} }
fn test_a_simple_tcp_client_html_page() { fn test_a_simple_tcp_client_html_page() {
received := simple_tcp_client({ received := simple_tcp_client(path: '/html_page') or {
path: '/html_page'
}) or {
assert err == '' assert err == ''
return return
} }
@ -97,9 +93,7 @@ fn assert_common_http_headers(x http.Response) {
} }
fn test_http_client_index() { fn test_http_client_index() {
x := http.get('http://127.0.0.1:$sport/') or { x := http.get('http://127.0.0.1:$sport/') or { panic(err) }
panic(err)
}
assert_common_http_headers(x) assert_common_http_headers(x)
assert x.headers['Content-Type'] == 'text/plain' assert x.headers['Content-Type'] == 'text/plain'
assert x.text == 'Welcome to VWeb' assert x.text == 'Welcome to VWeb'
@ -112,61 +106,45 @@ fn test_http_client_404() {
'http://127.0.0.1:$sport/unknown', 'http://127.0.0.1:$sport/unknown',
] ]
for url in url_404_list { for url in url_404_list {
res := http.get(url) or { res := http.get(url) or { panic(err) }
panic(err)
}
assert res.status_code == 404 assert res.status_code == 404
} }
} }
fn test_http_client_simple() { fn test_http_client_simple() {
x := http.get('http://127.0.0.1:$sport/simple') or { x := http.get('http://127.0.0.1:$sport/simple') or { panic(err) }
panic(err)
}
assert_common_http_headers(x) assert_common_http_headers(x)
assert x.headers['Content-Type'] == 'text/plain' assert x.headers['Content-Type'] == 'text/plain'
assert x.text == 'A simple result' assert x.text == 'A simple result'
} }
fn test_http_client_html_page() { fn test_http_client_html_page() {
x := http.get('http://127.0.0.1:$sport/html_page') or { x := http.get('http://127.0.0.1:$sport/html_page') or { panic(err) }
panic(err)
}
assert_common_http_headers(x) assert_common_http_headers(x)
assert x.headers['Content-Type'] == 'text/html' assert x.headers['Content-Type'] == 'text/html'
assert x.text == '<h1>ok</h1>' assert x.text == '<h1>ok</h1>'
} }
fn test_http_client_settings_page() { fn test_http_client_settings_page() {
x := http.get('http://127.0.0.1:$sport/bilbo/settings') or { x := http.get('http://127.0.0.1:$sport/bilbo/settings') or { panic(err) }
panic(err)
}
assert_common_http_headers(x) assert_common_http_headers(x)
assert x.text == 'username: bilbo' assert x.text == 'username: bilbo'
// //
y := http.get('http://127.0.0.1:$sport/kent/settings') or { y := http.get('http://127.0.0.1:$sport/kent/settings') or { panic(err) }
panic(err)
}
assert_common_http_headers(y) assert_common_http_headers(y)
assert y.text == 'username: kent' assert y.text == 'username: kent'
} }
fn test_http_client_user_repo_settings_page() { fn test_http_client_user_repo_settings_page() {
x := http.get('http://127.0.0.1:$sport/bilbo/gostamp/settings') or { x := http.get('http://127.0.0.1:$sport/bilbo/gostamp/settings') or { panic(err) }
panic(err)
}
assert_common_http_headers(x) assert_common_http_headers(x)
assert x.text == 'username: bilbo | repository: gostamp' assert x.text == 'username: bilbo | repository: gostamp'
// //
y := http.get('http://127.0.0.1:$sport/kent/golang/settings') or { y := http.get('http://127.0.0.1:$sport/kent/golang/settings') or { panic(err) }
panic(err)
}
assert_common_http_headers(y) assert_common_http_headers(y)
assert y.text == 'username: kent | repository: golang' assert y.text == 'username: kent | repository: golang'
// //
z := http.get('http://127.0.0.1:$sport/missing/golang/settings') or { z := http.get('http://127.0.0.1:$sport/missing/golang/settings') or { panic(err) }
panic(err)
}
assert z.status_code == 404 assert z.status_code == 404
} }
@ -181,17 +159,13 @@ fn test_http_client_json_post() {
age: 123 age: 123
} }
json_for_ouser := json.encode(ouser) json_for_ouser := json.encode(ouser)
x := http.post_json('http://127.0.0.1:$sport/json_echo', json_for_ouser) or { x := http.post_json('http://127.0.0.1:$sport/json_echo', json_for_ouser) or { panic(err) }
panic(err)
}
$if debug_net_socket_client ? { $if debug_net_socket_client ? {
eprintln('json response: $x') eprintln('json response: $x')
} }
assert x.headers['Content-Type'] == 'application/json' assert x.headers['Content-Type'] == 'application/json'
assert x.text == json_for_ouser assert x.text == json_for_ouser
nuser := json.decode(User, x.text) or { nuser := json.decode(User, x.text) or { User{} }
User{}
}
assert '$ouser' == '$nuser' assert '$ouser' == '$nuser'
} }
@ -207,12 +181,9 @@ fn test_http_client_shutdown_does_not_work_without_a_cookie() {
fn testsuite_end() { fn testsuite_end() {
// This test is guaranteed to be called last. // This test is guaranteed to be called last.
// It sends a request to the server to shutdown. // It sends a request to the server to shutdown.
x := http.fetch('http://127.0.0.1:$sport/shutdown', { x := http.fetch('http://127.0.0.1:$sport/shutdown', method: .get, cookies: {
method: .get
cookies: {
'skey': 'superman' 'skey': 'superman'
} }) or {
}) or {
assert err == '' assert err == ''
return return
} }

View File

@ -86,9 +86,7 @@ pub fn (mut app App) json() vweb.Result {
} }
pub fn (mut app App) shutdown() vweb.Result { pub fn (mut app App) shutdown() vweb.Result {
session_key := app.vweb.get_cookie('skey') or { session_key := app.vweb.get_cookie('skey') or { return app.vweb.not_found() }
return app.vweb.not_found()
}
if session_key != 'superman' { if session_key != 'superman' {
return app.vweb.not_found() return app.vweb.not_found()
} }

View File

@ -13,17 +13,15 @@ const (
// compile_file compiles the content of a file by the given path as a template // compile_file compiles the content of a file by the given path as a template
pub fn compile_file(path string, fn_name string) string { pub fn compile_file(path string, fn_name string) string {
html := os.read_file(path) or { html := os.read_file(path) or { panic('html failed') }
panic('html failed')
}
return compile_template(html, fn_name) return compile_template(html, fn_name)
} }
enum State { enum State {
html html
css // <style> css // <style>
js // <script> js // <script>
//span // span.{ // span // span.{
} }
pub fn compile_template(html_ string, fn_name string) string { pub fn compile_template(html_ string, fn_name string) string {
@ -45,15 +43,15 @@ pub fn compile_template(html_ string, fn_name string) string {
footer = f.trim_space().replace("\'", '"') footer = f.trim_space().replace("\'", '"')
html += footer html += footer
} }
mut lines := html.split_into_lines() mut lines := html.split_into_lines()
lstartlength := lines.len * 30
mut s := strings.new_builder(1000) mut s := strings.new_builder(1000)
// base := path.all_after_last('/').replace('.html', '') // base := path.all_after_last('/').replace('.html', '')
s.writeln(" s.writeln("
import strings import strings
// === vweb html template === // === vweb html template ===
fn vweb_tmpl_${fn_name}() { fn vweb_tmpl_${fn_name}() {
mut sb := strings.new_builder(${lines.len * 30})\n mut sb := strings.new_builder($lstartlength)\n
header := \' \' // TODO remove header := \' \' // TODO remove
_ = header _ = header
footer := \' \' // TODO remove footer := \' \' // TODO remove
@ -63,25 +61,21 @@ _ = footer
s.write(str_start) s.write(str_start)
mut state := State.html mut state := State.html
mut in_span := false mut in_span := false
//for _line in lines { // for _line in lines {
for i := 0; i < lines.len; i ++ { for i := 0; i < lines.len; i++ {
line := lines[i].trim_space() line := lines[i].trim_space()
if line == '<style>' { if line == '<style>' {
state = .css state = .css
} else if line == '</style>' { } else if line == '</style>' {
state = .html state = .html
} } else if line == '<script>' {
else if line == '<script>' {
state = .js state = .js
} } else if line == '</script>' {
else if line == '</script>' {
state = .html state = .html
} }
if line.contains('@include ') && false { if line.contains('@include ') && false {
// TODO // TODO
pos := line.index('@include ') or { pos := line.index('@include ') or { continue }
continue
}
file_name := line[pos + 9..] file_name := line[pos + 9..]
file_path := os.join_path('templates', '${file_name}.html') file_path := os.join_path('templates', '${file_name}.html')
mut file_content := os.read_file(file_path) or { mut file_content := os.read_file(file_path) or {
@ -90,29 +84,23 @@ _ = footer
file_content = file_content.replace("\'", '"') file_content = file_content.replace("\'", '"')
lines2 := file_content.split_into_lines() lines2 := file_content.split_into_lines()
for l in lines2 { for l in lines2 {
lines.insert(i+1, l) lines.insert(i + 1, l)
} }
continue continue
//s.writeln(file_content) // s.writeln(file_content)
} else if line.contains('@js ') { } else if line.contains('@js ') {
pos := line.index('@js') or { pos := line.index('@js') or { continue }
continue
}
s.write('<script src="') s.write('<script src="')
s.write(line[pos + 5..line.len-1]) s.write(line[pos + 5..line.len - 1])
s.writeln('"></script>') s.writeln('"></script>')
} else if line.contains('@css ') { } else if line.contains('@css ') {
pos := line.index('@css') or { pos := line.index('@css') or { continue }
continue
}
s.write('<link href="') s.write('<link href="')
s.write(line[pos + 6..line.len-1]) s.write(line[pos + 6..line.len - 1])
s.writeln('" rel="stylesheet" type="text/css">') s.writeln('" rel="stylesheet" type="text/css">')
} else if line.contains('@if ') { } else if line.contains('@if ') {
s.writeln(str_end) s.writeln(str_end)
pos := line.index('@if') or { pos := line.index('@if') or { continue }
continue
}
s.writeln('if ' + line[pos + 4..] + '{') s.writeln('if ' + line[pos + 4..] + '{')
s.writeln(str_start) s.writeln(str_start)
} else if line.contains('@end') { } else if line.contains('@end') {
@ -125,16 +113,14 @@ _ = footer
s.writeln(str_start) s.writeln(str_start)
} else if line.contains('@for') { } else if line.contains('@for') {
s.writeln(str_end) s.writeln(str_end)
pos := line.index('@for') or { pos := line.index('@for') or { continue }
continue
}
s.writeln('for ' + line[pos + 4..] + '{') s.writeln('for ' + line[pos + 4..] + '{')
s.writeln(str_start) s.writeln(str_start)
} else if state == .html && line.contains('span.') && line.ends_with('{') { } else if state == .html && line.contains('span.') && line.ends_with('{') {
// `span.header {` => `<span class='header'>` // `span.header {` => `<span class='header'>`
class := line.find_between('span.', '{').trim_space() class := line.find_between('span.', '{').trim_space()
s.writeln('<span class="$class">') s.writeln('<span class="$class">')
in_span = true in_span = true
} else if state == .html && line.contains('.') && line.ends_with('{') { } else if state == .html && line.contains('.') && line.ends_with('{') {
// `.header {` => `<div class='header'>` // `.header {` => `<div class='header'>`
class := line.find_between('.', '{').trim_space() class := line.find_between('.', '{').trim_space()
@ -162,4 +148,3 @@ _ = footer
s.writeln('// === end of vweb html template ===') s.writeln('// === end of vweb html template ===')
return s.str() return s.str()
} }

View File

@ -20,20 +20,20 @@ pub const (
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_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' http_500 = 'HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n${headers_close}500 Internal Server Error'
mime_types = { mime_types = {
'.css': 'text/css; charset=utf-8' '.css': 'text/css; charset=utf-8'
'.gif': 'image/gif' '.gif': 'image/gif'
'.htm': 'text/html; charset=utf-8' '.htm': 'text/html; charset=utf-8'
'.html': 'text/html; charset=utf-8' '.html': 'text/html; charset=utf-8'
'.jpg': 'image/jpeg' '.jpg': 'image/jpeg'
'.js': 'application/javascript' '.js': 'application/javascript'
'.json': 'application/json' '.json': 'application/json'
'.md': 'text/markdown; charset=utf-8' '.md': 'text/markdown; charset=utf-8'
'.pdf': 'application/pdf' '.pdf': 'application/pdf'
'.png': 'image/png' '.png': 'image/png'
'.svg': 'image/svg+xml' '.svg': 'image/svg+xml'
'.txt': 'text/plain; charset=utf-8' '.txt': 'text/plain; charset=utf-8'
'.wasm': 'application/wasm' '.wasm': 'application/wasm'
'.xml': 'text/xml; charset=utf-8' '.xml': 'text/xml; charset=utf-8'
} }
max_http_post_size = 1024 * 1024 max_http_post_size = 1024 * 1024
default_port = 8080 default_port = 8080
@ -46,8 +46,8 @@ mut:
content_type string = 'text/plain' content_type string = 'text/plain'
status string = '200 OK' status string = '200 OK'
pub: pub:
req http.Request req http.Request
conn net.TcpConn conn net.TcpConn
// TODO Response // TODO Response
pub mut: pub mut:
form map[string]string form map[string]string
@ -117,7 +117,9 @@ pub fn (mut ctx Context) redirect(url string) Result {
return Result{} return Result{}
} }
ctx.done = true ctx.done = true
send_string(ctx.conn, 'HTTP/1.1 302 Found\r\nLocation: ${url}${ctx.headers}\r\n${headers_close}') or { return Result{} } send_string(ctx.conn, 'HTTP/1.1 302 Found\r\nLocation: $url$ctx.headers\r\n$headers_close') or {
return Result{}
}
return Result{} return Result{}
} }
@ -126,8 +128,8 @@ pub fn (mut ctx Context) not_found() Result {
return Result{} return Result{}
} }
ctx.done = true ctx.done = true
send_string(ctx.conn, http_404) or {} send_string(ctx.conn, http_404) or { }
return vweb.Result{} return Result{}
} }
pub fn (mut ctx Context) set_cookie(cookie Cookie) { pub fn (mut ctx Context) set_cookie(cookie Cookie) {
@ -212,11 +214,11 @@ pub fn run_app<T>(mut app T, port int) {
for { for {
mut conn := l.accept() or { panic('accept() failed') } mut conn := l.accept() or { panic('accept() failed') }
handle_conn<T>(mut conn, mut app) handle_conn<T>(mut conn, mut app)
//app.vweb.page_gen_time = time.ticks() - t // app.vweb.page_gen_time = time.ticks() - t
//eprintln('handle conn() took ${time.ticks()-t}ms') // eprintln('handle conn() took ${time.ticks()-t}ms')
//message := readall(conn) // message := readall(conn)
//println(message) // println(message)
/* /*
if message.len > max_http_post_size { if message.len > max_http_post_size {
println('message.len = $message.len > max_http_post_size') println('message.len = $message.len > max_http_post_size')
conn.send_string(http_500) or {} conn.send_string(http_500) or {}
@ -238,13 +240,13 @@ pub fn run_app<T>(mut app T, port int) {
fn handle_conn<T>(mut conn net.TcpConn, mut app T) { fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
conn.set_read_timeout(1 * time.second) conn.set_read_timeout(1 * time.second)
defer { conn.close() or {} } defer {
//fn handle_conn<T>(conn net.Socket, app_ T) T { conn.close() or { }
//mut app := app_ }
//first_line := strip(lines[0]) // fn handle_conn<T>(conn net.Socket, app_ T) T {
// mut app := app_
// first_line := strip(lines[0])
mut reader := io.new_buffered_reader(reader: io.make_reader(conn)) mut reader := io.new_buffered_reader(reader: io.make_reader(conn))
page_gen_start := time.ticks() page_gen_start := time.ticks()
first_line := reader.read_line() or { first_line := reader.read_line() or {
println('Failed first_line') println('Failed first_line')
@ -259,36 +261,34 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
vals := first_line.split(' ') vals := first_line.split(' ')
if vals.len < 2 { if vals.len < 2 {
println('no vals for http') println('no vals for http')
send_string(conn, http_500) or {} send_string(conn, http_500) or { }
return return
} }
mut headers := []string{} mut headers := []string{}
mut body := '' mut body := ''
mut in_headers := true mut in_headers := true
mut len := 0 mut len := 0
//for line in lines[1..] { // for line in lines[1..] {
for _ in 0..100 { for _ in 0 .. 100 {
//println(j) // println(j)
line := reader.read_line() or { line := reader.read_line() or {
println('Failed read_line') println('Failed read_line')
break break
} }
sline := strip(line) sline := strip(line)
if sline == '' { if sline == '' {
//if in_headers { // if in_headers {
// End of headers, no body => exit // End of headers, no body => exit
if len == 0 { if len == 0 {
break break
} }
//} //else { //} //else {
// End of body // End of body
//break // break
//} //}
// read body // read body
read_body := io.read_all(reader: reader) or { []byte{} } read_body := io.read_all(reader: reader) or { []byte{} }
body += read_body.bytestr() body += read_body.bytestr()
break break
} }
if in_headers { if in_headers {
@ -343,7 +343,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
mime_type := app.vweb.static_mime_types[static_file_name] mime_type := app.vweb.static_mime_types[static_file_name]
if static_file != '' && mime_type != '' { if static_file != '' && mime_type != '' {
data := os.read_file(static_file) or { data := os.read_file(static_file) or {
send_string(conn, http_404) or {} send_string(conn, http_404) or { }
return return
} }
app.vweb.send_response_to_client(mime_type, data) app.vweb.send_response_to_client(mime_type, data)
@ -491,7 +491,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
} }
if action == '' { if action == '' {
// site not found // site not found
send_string(conn, http_404) or {} send_string(conn, http_404) or { }
return return
} }
$for method in T.methods { $for method in T.methods {
@ -526,12 +526,8 @@ fn (mut ctx Context) parse_form(s string) {
if keyval.len != 2 { if keyval.len != 2 {
continue continue
} }
key := urllib.query_unescape(keyval[0]) or { key := urllib.query_unescape(keyval[0]) or { continue }
continue val := urllib.query_unescape(keyval[1]) or { continue }
}
val := urllib.query_unescape(keyval[1]) or {
continue
}
$if debug { $if debug {
println('http form "$key" => "$val"') println('http form "$key" => "$val"')
} }
@ -543,9 +539,7 @@ fn (mut ctx Context) parse_form(s string) {
} }
fn (mut ctx Context) scan_static_directory(directory_path string, mount_path string) { fn (mut ctx Context) scan_static_directory(directory_path string, mount_path string) {
files := os.ls(directory_path) or { files := os.ls(directory_path) or { panic(err) }
panic(err)
}
if files.len > 0 { if files.len > 0 {
for file in files { for file in files {
full_path := directory_path + '/' + file full_path := directory_path + '/' + file
@ -556,8 +550,7 @@ fn (mut ctx Context) scan_static_directory(directory_path string, mount_path str
// Rudimentary guard against adding files not in mime_types. // Rudimentary guard against adding files not in mime_types.
// Use serve_static directly to add non-standard mime types. // Use serve_static directly to add non-standard mime types.
if ext in mime_types { if ext in mime_types {
ctx.serve_static(mount_path + '/' + file, full_path, ctx.serve_static(mount_path + '/' + file, full_path, mime_types[ext])
mime_types[ext])
} }
} }
} }
@ -639,7 +632,6 @@ fn filter(s string) string {
pub type RawHtml = string pub type RawHtml = string
fn send_string(conn net.TcpConn, s string) ? { fn send_string(conn net.TcpConn, s string) ? {
conn.write(s.bytes())? conn.write(s.bytes()) ?
} }