forked from vieter-v/vieter
				
			Code now passes vet
							parent
							
								
									1f8f16fe8d
								
							
						
					
					
						commit
						b86c6b5e16
					
				|  | @ -5,7 +5,6 @@ import os | |||
| import log | ||||
| import io | ||||
| import pkg | ||||
| import archive | ||||
| import repo | ||||
| 
 | ||||
| const port = 8000 | ||||
|  | @ -110,7 +109,5 @@ fn main() { | |||
| 		return | ||||
| 	} | ||||
| 	// println(info) | ||||
| 	println(res.info) | ||||
| 	print(res.files) | ||||
| 	println(res.info.to_desc()) | ||||
| 	print(res) | ||||
| } | ||||
|  |  | |||
|  | @ -89,6 +89,7 @@ mut: | |||
| 	checkdepends []string | ||||
| } | ||||
| 
 | ||||
| // parse_pkg_info_string parses a PkgInfo object from a string | ||||
| fn parse_pkg_info_string(pkg_info_str &string) ?PkgInfo { | ||||
| 	mut pkg_info := PkgInfo{} | ||||
| 
 | ||||
|  | @ -140,7 +141,7 @@ fn parse_pkg_info_string(pkg_info_str &string) ?PkgInfo { | |||
| 	return pkg_info | ||||
| } | ||||
| 
 | ||||
| // Extracts the file list & .PKGINFO contents from an archive | ||||
| // read_pkg extracts the file list & .PKGINFO contents from an archive | ||||
| // NOTE: this command currently only supports zstd-compressed tarballs | ||||
| pub fn read_pkg(pkg_path string) ?Pkg { | ||||
| 	if !os.is_file(pkg_path) { | ||||
|  | @ -166,9 +167,9 @@ pub fn read_pkg(pkg_path string) ?Pkg { | |||
| 		return error('Failed to open package.') | ||||
| 	} | ||||
| 
 | ||||
| 	// We iterate over every header in search of the .PKGINFO one | ||||
| 	mut buf := voidptr(0) | ||||
| 	mut files := []string{} | ||||
| 
 | ||||
| 	for C.archive_read_next_header(a, &entry) == C.ARCHIVE_OK { | ||||
| 		pathname := C.archive_entry_pathname(entry) | ||||
| 
 | ||||
|  | @ -198,7 +199,7 @@ pub fn read_pkg(pkg_path string) ?Pkg { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Represent a PkgInfo struct as a desc file | ||||
| // to_desc returns a desc file valid string representation | ||||
| pub fn (p &PkgInfo) to_desc() string { | ||||
| 	// TODO calculate md5 & sha256 instead of believing the file | ||||
| 	mut desc := '' | ||||
|  |  | |||
							
								
								
									
										13
									
								
								src/repo.v
								
								
								
								
							
							
						
						
									
										13
									
								
								src/repo.v
								
								
								
								
							|  | @ -1,7 +1,6 @@ | |||
| module repo | ||||
| 
 | ||||
| import os | ||||
| import archive | ||||
| 
 | ||||
| const pkgs_subpath = 'pkgs' | ||||
| 
 | ||||
|  | @ -22,35 +21,37 @@ pub: | |||
| 	pkg_dir string [required] | ||||
| } | ||||
| 
 | ||||
| // Returns whether the repository contains the given package. | ||||
| // contains returns whether the repository contains the given package. | ||||
| pub fn (r &Repo) contains(pkg string) bool { | ||||
| 	return os.exists(os.join_path(r.repo_dir, 'files', pkg)) | ||||
| } | ||||
| 
 | ||||
| // Adds the given package to the repo. If false, the package was already | ||||
| // add adds the given package to the repo. If false, the package was already | ||||
| // present in the repository. | ||||
| pub fn (r &Repo) add(pkg string) ?bool { | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // Re-generate the db & files archives. | ||||
| // generate re-generates the db & files archives. | ||||
| fn (r &Repo) genenerate() ? { | ||||
| } | ||||
| 
 | ||||
| // Returns path to the given package, prepended with the repo's path. | ||||
| // pkg_path returns path to the given package, prepended with the repo's path. | ||||
| pub fn (r &Repo) pkg_path(pkg string) string { | ||||
| 	return os.join_path_single(r.pkg_dir, pkg) | ||||
| } | ||||
| 
 | ||||
| // exists checks whether a package file exists | ||||
| pub fn (r &Repo) exists(pkg string) bool { | ||||
| 	return os.exists(r.pkg_path(pkg)) | ||||
| } | ||||
| 
 | ||||
| // Returns the full path to the database file | ||||
| // db_path returns the full path to the database file | ||||
| pub fn (r &Repo) db_path() string { | ||||
| 	return os.join_path_single(r.repo_dir, 'repo.tar.gz') | ||||
| } | ||||
| 
 | ||||
| // add_package adds a package to the repository | ||||
| pub fn (r &Repo) add_package(pkg_path string) ? { | ||||
| 	mut res := os.Result{} | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import time | |||
| 
 | ||||
| const prefixes = ['B', 'KB', 'MB', 'GB'] | ||||
| 
 | ||||
| // pretty_bytes converts a byte count to human-readable version | ||||
| fn pretty_bytes(bytes int) string { | ||||
| 	mut i := 0 | ||||
| 	mut n := f32(bytes) | ||||
|  | @ -23,6 +24,7 @@ fn is_pkg_name(s string) bool { | |||
| 	return s.contains('.pkg') | ||||
| } | ||||
| 
 | ||||
| // get_root handles a GET request for a file on the root | ||||
| ['/:filename'; get] | ||||
| fn (mut app App) get_root(filename string) web.Result { | ||||
| 	mut full_path := '' | ||||
|  | @ -88,6 +90,7 @@ fn (mut app App) get_root(filename string) web.Result { | |||
| // 	return app.text('Package added successfully.') | ||||
| // } | ||||
| 
 | ||||
| // add_package PUT a new package to the server | ||||
| ['/add'; put] | ||||
| pub fn (mut app App) add_package() web.Result { | ||||
| 	return app.text('') | ||||
|  |  | |||
|  | @ -2,28 +2,34 @@ module web | |||
| 
 | ||||
| import log | ||||
| 
 | ||||
| // log reate a log message with the given level | ||||
| pub fn (mut ctx Context) log(msg &string, level log.Level) { | ||||
| 	lock ctx.logger { | ||||
| 		ctx.logger.send_output(msg, level) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // lfatal create a log message with the fatal level | ||||
| pub fn (mut ctx Context) lfatal(msg &string) { | ||||
| 	ctx.log(msg, log.Level.fatal) | ||||
| } | ||||
| 
 | ||||
| // lerror create a log message with the error level | ||||
| pub fn (mut ctx Context) lerror(msg &string) { | ||||
| 	ctx.log(msg, log.Level.error) | ||||
| } | ||||
| 
 | ||||
| // lwarn create a log message with the warn level | ||||
| pub fn (mut ctx Context) lwarn(msg &string) { | ||||
| 	ctx.log(msg, log.Level.warn) | ||||
| } | ||||
| 
 | ||||
| // linfo create a log message with the info level | ||||
| pub fn (mut ctx Context) linfo(msg &string) { | ||||
| 	ctx.log(msg, log.Level.info) | ||||
| } | ||||
| 
 | ||||
| // ldebug create a log message with the debug level | ||||
| pub fn (mut ctx Context) ldebug(msg &string) { | ||||
| 	ctx.log(msg, log.Level.debug) | ||||
| } | ||||
|  |  | |||
|  | @ -187,14 +187,14 @@ struct Route { | |||
| } | ||||
| 
 | ||||
| // Defining this method is optional. | ||||
| // This method called at server start. | ||||
| // init_server is called at server start. | ||||
| // You can use it for initializing globals. | ||||
| pub fn (ctx Context) init_server() { | ||||
| 	eprintln('init_server() has been deprecated, please init your web app in `fn main()`') | ||||
| } | ||||
| 
 | ||||
| // Defining this method is optional. | ||||
| // This method called before every request (aka middleware). | ||||
| // before_request is called before every request (aka middleware). | ||||
| // Probably you can use it for check user session cookie or add header. | ||||
| pub fn (ctx Context) before_request() {} | ||||
| 
 | ||||
|  | @ -206,7 +206,7 @@ pub struct Cookie { | |||
| 	http_only bool | ||||
| } | ||||
| 
 | ||||
| // web intern function | ||||
| // send_response_to_client sends a response to the client | ||||
| [manualfree] | ||||
| pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bool { | ||||
| 	if ctx.done { | ||||
|  | @ -230,33 +230,33 @@ pub fn (mut ctx Context) send_response_to_client(mimetype string, res string) bo | |||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // Response HTTP_OK with s as payload with content-type `text/html` | ||||
| // html HTTP_OK with s as payload with content-type `text/html` | ||||
| pub fn (mut ctx Context) html(s string) Result { | ||||
| 	ctx.send_response_to_client('text/html', s) | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Response HTTP_OK with s as payload with content-type `text/plain` | ||||
| // text HTTP_OK with s as payload with content-type `text/plain` | ||||
| pub fn (mut ctx Context) text(s string) Result { | ||||
| 	ctx.send_response_to_client('text/plain', s) | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Response HTTP_OK with json_s as payload with content-type `application/json` | ||||
| // json<T> HTTP_OK with json_s as payload with content-type `application/json` | ||||
| pub fn (mut ctx Context) json<T>(j T) Result { | ||||
| 	json_s := json.encode(j) | ||||
| 	ctx.send_response_to_client('application/json', json_s) | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Response HTTP_OK with a pretty-printed JSON result | ||||
| // json_pretty<T> Response HTTP_OK with a pretty-printed JSON result | ||||
| pub fn (mut ctx Context) json_pretty<T>(j T) Result { | ||||
| 	json_s := json.encode_pretty(j) | ||||
| 	ctx.send_response_to_client('application/json', json_s) | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Response HTTP_OK with file as payload | ||||
| // file Response HTTP_OK with file as payload | ||||
| // This function manually implements responses because it needs to stream the file contents | ||||
| pub fn (mut ctx Context) file(f_path string) Result { | ||||
| 	if ctx.done { | ||||
|  | @ -329,13 +329,13 @@ pub fn (mut ctx Context) file(f_path string) Result { | |||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Response HTTP_OK with s as payload | ||||
| // ok Response HTTP_OK with s as payload | ||||
| pub fn (mut ctx Context) ok(s string) Result { | ||||
| 	ctx.send_response_to_client(ctx.content_type, s) | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Response a server error | ||||
| // server_error Response a server error | ||||
| pub fn (mut ctx Context) server_error(ecode int) Result { | ||||
| 	$if debug { | ||||
| 		eprintln('> ctx.server_error ecode: $ecode') | ||||
|  | @ -347,7 +347,7 @@ pub fn (mut ctx Context) server_error(ecode int) Result { | |||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Redirect to an url | ||||
| // redirect Redirect to an url | ||||
| pub fn (mut ctx Context) redirect(url string) Result { | ||||
| 	if ctx.done { | ||||
| 		return Result{} | ||||
|  | @ -360,7 +360,7 @@ pub fn (mut ctx Context) redirect(url string) Result { | |||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Send an not_found response | ||||
| // not_found Send an not_found response | ||||
| pub fn (mut ctx Context) not_found() Result { | ||||
| 	if ctx.done { | ||||
| 		return Result{} | ||||
|  | @ -370,7 +370,7 @@ pub fn (mut ctx Context) not_found() Result { | |||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // Sets a cookie | ||||
| // set_cookie Sets a cookie | ||||
| pub fn (mut ctx Context) set_cookie(cookie Cookie) { | ||||
| 	mut cookie_data := []string{} | ||||
| 	mut secure := if cookie.secure { 'Secure;' } else { '' } | ||||
|  | @ -383,17 +383,17 @@ pub fn (mut ctx Context) set_cookie(cookie Cookie) { | |||
| 	ctx.add_header('Set-Cookie', '$cookie.name=$cookie.value; $data') | ||||
| } | ||||
| 
 | ||||
| // Sets the response content type | ||||
| // set_content_type Sets the response content type | ||||
| pub fn (mut ctx Context) set_content_type(typ string) { | ||||
| 	ctx.content_type = typ | ||||
| } | ||||
| 
 | ||||
| // Sets a cookie with a `expire_data` | ||||
| // set_cookie_with_expire_date Sets a cookie with a `expire_data` | ||||
| pub fn (mut ctx Context) set_cookie_with_expire_date(key string, val string, expire_date time.Time) { | ||||
| 	ctx.add_header('Set-Cookie', '$key=$val;  Secure; HttpOnly; expires=$expire_date.utc_string()') | ||||
| } | ||||
| 
 | ||||
| // Gets a cookie by a key | ||||
| // get_cookie Gets a cookie by a key | ||||
| pub fn (ctx &Context) get_cookie(key string) ?string { // TODO refactor | ||||
| 	mut cookie_header := ctx.get_header('cookie') | ||||
| 	if cookie_header == '' { | ||||
|  | @ -413,7 +413,7 @@ pub fn (ctx &Context) get_cookie(key string) ?string { // TODO refactor | |||
| 	return error('Cookie not found') | ||||
| } | ||||
| 
 | ||||
| // Sets the response status | ||||
| // set_status Sets the response status | ||||
| pub fn (mut ctx Context) set_status(code int, desc string) { | ||||
| 	if code < 100 || code > 599 { | ||||
| 		ctx.status = '500 Internal Server Error' | ||||
|  | @ -422,12 +422,12 @@ pub fn (mut ctx Context) set_status(code int, desc string) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Adds an header to the response with key and val | ||||
| // add_header Adds an header to the response with key and val | ||||
| pub fn (mut ctx Context) add_header(key string, val string) { | ||||
| 	ctx.header.add_custom(key, val) or {} | ||||
| } | ||||
| 
 | ||||
| // Returns the header data from the key | ||||
| // get_header Returns the header data from the key | ||||
| pub fn (ctx &Context) get_header(key string) string { | ||||
| 	return ctx.req.header.get_custom(key) or { '' } | ||||
| } | ||||
|  | @ -436,7 +436,7 @@ interface DbInterface { | |||
| 	db voidptr | ||||
| } | ||||
| 
 | ||||
| // run_app | ||||
| // run runs the app | ||||
| [manualfree] | ||||
| pub fn run<T>(global_app &T, port int) { | ||||
| 	mut l := net.listen_tcp(.ip6, ':$port') or { panic('failed to listen $err.code $err') } | ||||
|  | @ -478,6 +478,7 @@ pub fn run<T>(global_app &T, port int) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // handle_conn handles a connection | ||||
| [manualfree] | ||||
| fn handle_conn<T>(mut conn net.TcpConn, mut app T, routes map[string]Route) { | ||||
| 	conn.set_read_timeout(30 * time.second) | ||||
|  | @ -615,6 +616,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T, routes map[string]Route) { | |||
| 	conn.write(web.http_404.bytes()) or {} | ||||
| } | ||||
| 
 | ||||
| // route_matches returns wether a route matches | ||||
| fn route_matches(url_words []string, route_words []string) ?[]string { | ||||
| 	// URL path should be at least as long as the route path | ||||
| 	// except for the catchall route (`/:path...`) | ||||
|  | @ -657,7 +659,7 @@ fn route_matches(url_words []string, route_words []string) ?[]string { | |||
| 	return params | ||||
| } | ||||
| 
 | ||||
| // check if request is for a static file and serves it | ||||
| // serve_if_static<T> checks if request is for a static file and serves it | ||||
| // returns true if we served a static file, false otherwise | ||||
| [manualfree] | ||||
| fn serve_if_static<T>(mut app T, url urllib.URL) bool { | ||||
|  | @ -676,6 +678,7 @@ fn serve_if_static<T>(mut app T, url urllib.URL) bool { | |||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // scan_static_directory makes a static route for each file in a directory | ||||
| fn (mut ctx Context) scan_static_directory(directory_path string, mount_path string) { | ||||
| 	files := os.ls(directory_path) or { panic(err) } | ||||
| 	if files.len > 0 { | ||||
|  | @ -695,7 +698,7 @@ fn (mut ctx Context) scan_static_directory(directory_path string, mount_path str | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Handles a directory static | ||||
| // handle_static Handles a directory static | ||||
| // If `root` is set the mount path for the dir will be in '/' | ||||
| pub fn (mut ctx Context) handle_static(directory_path string, root bool) bool { | ||||
| 	if ctx.done || !os.exists(directory_path) { | ||||
|  | @ -724,7 +727,7 @@ pub fn (mut ctx Context) mount_static_folder_at(directory_path string, mount_pat | |||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // Serves a file static | ||||
| // serve_static Serves a file static | ||||
| // `url` is the access path on the site, `file_path` is the real path to the file, `mime_type` is the file type | ||||
| pub fn (mut ctx Context) serve_static(url string, file_path string) { | ||||
| 	ctx.static_files[url] = file_path | ||||
|  | @ -733,7 +736,7 @@ pub fn (mut ctx Context) serve_static(url string, file_path string) { | |||
| 	ctx.static_mime_types[url] = web.mime_types[ext] | ||||
| } | ||||
| 
 | ||||
| // Returns the ip address from the current user | ||||
| // ip Returns the ip address from the current user | ||||
| pub fn (ctx &Context) ip() string { | ||||
| 	mut ip := ctx.req.header.get(.x_forwarded_for) or { '' } | ||||
| 	if ip == '' { | ||||
|  | @ -749,22 +752,23 @@ pub fn (ctx &Context) ip() string { | |||
| 	return ip | ||||
| } | ||||
| 
 | ||||
| // Set s to the form error | ||||
| // error Set s to the form error | ||||
| pub fn (mut ctx Context) error(s string) { | ||||
| 	println('web error: $s') | ||||
| 	ctx.form_error = s | ||||
| } | ||||
| 
 | ||||
| // Returns an empty result | ||||
| // not_found Returns an empty result | ||||
| pub fn not_found() Result { | ||||
| 	return Result{} | ||||
| } | ||||
| 
 | ||||
| // send_string | ||||
| fn send_string(mut conn net.TcpConn, s string) ? { | ||||
| 	conn.write(s.bytes()) ? | ||||
| } | ||||
| 
 | ||||
| // Do not delete. | ||||
| // filter Do not delete. | ||||
| // It used by `vlib/v/gen/c/str_intp.v:130` for string interpolation inside web templates | ||||
| // TODO: move it to template render | ||||
| fn filter(s string) string { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue