Code now passes vet
ci/woodpecker/push/builder unknown status Details
ci/woodpecker/push/publish unknown status Details
ci/woodpecker/push/build Pipeline was successful Details
ci/woodpecker/push/lint Pipeline was successful Details
ci/woodpecker/push/build_arm64 Pipeline was successful Details

pull/48/head
Jef Roosens 2022-01-14 22:46:04 +01:00
parent 1f8f16fe8d
commit b86c6b5e16
Signed by: Jef Roosens
GPG Key ID: 955C0660072F691F
6 changed files with 52 additions and 40 deletions

View File

@ -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)
}

View File

@ -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 := ''

View File

@ -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{}

View File

@ -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('')

View File

@ -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)
}

View File

@ -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 {