Skip to content
Browse files

rename file extension

  • Loading branch information...
1 parent aa9c869 commit 9e2cea5780427a647f4ea00177a54a6c02812467 @chzyer chzyer committed
Showing with 567 additions and 0 deletions.
  1. +32 −0 example/main.jl
  2. +7 −0 example/sub.jl
  3. +149 −0 julia_webserver_base.jl
  4. +100 −0 julia_webserver_iostream.jl
  5. +42 −0 julia_webserver_string.jl
  6. +215 −0 julia_webserver_template.jl
  7. +22 −0 julia_webserver_type.jl
View
32 example/main.jl
@@ -0,0 +1,32 @@
+load("../julia_webserver_base.jl")
+load("sub.jl")
+
+mainHandler = Handler(
+ function (f)
+ f.render("index")
+ end
+ ,
+ function (f)
+ c = f.get_argument("request", "2")
+ f.set_cookie("user", c)
+ f.write("thanks for post data $c")
+ end
+)
+
+SourceLoopHandler = Handler(
+ function (f)
+ f.render("source/loop")
+ end,
+ nothing
+)
+
+__handlers = [
+ (r"/", mainHandler),
+ (r"/source/loop", SourceLoopHandler),
+ (r"/[^/]+", subHandler),
+]
+_setting = {
+ debug = true
+}
+
+loop()
View
7 example/sub.jl
@@ -0,0 +1,7 @@
+subHandler = Handler(
+ function (f)
+ f.write("welcome to sub")
+ f.write("!haha")
+ f.senderror(502)
+ end
+, nothing)
View
149 julia_webserver_base.jl
@@ -0,0 +1,149 @@
+
+const DEFAULT_PROTOCOL = "HTTP/1.1"
+const DEFAULT_METHOD = "GET"
+const DEFAULT_PATH = "/"
+const LIB_PATH = "/home/cheney/juliawebserver/"
+const LIB_FILE_PREFIX = strcat(LIB_PATH, "julia_webserver_")
+const DEBUG = true
+
+function loads(mods::Array{ASCIIString})
+ for mod = mods
+ load(strcat(LIB_FILE_PREFIX, mod, ".jl"))
+ end
+end
+
+loads(["string", "type", "iostream", "template"])
+load("./ui/webserver/message_types.h")
+
+
+
+
+
+function __htmlfunc_senderror(code)
+ lib = {
+ 200 => "OK",
+ 301 => "Moved Permanently",
+ 302 => "Found",
+ 304 => "Forbidden",
+ 304 => "Not Modified",
+ 404 => "Not Found",
+ 405 => "Method Not Allowed",
+ 408 => "Request Timeout",
+ 500 => "Internal Server Error",
+ 502 => "Bad Gateway",
+ 504 => "Gateway Timeout"
+ }
+ "$code $(lib[code])"
+end
+
+function get_func(header)
+ data = {"html" => "", "status" => "200 OK", "cookie" => []}
+ func_base = Func(
+ data,header,
+
+ #write
+ function (str)
+ if str == nothing
+ return
+ end
+ func_base.data["html"] = strcat(func_base.data["html"], ASCIIString(str.data))
+ end,
+
+ #senderror
+ function (code)
+ func_base.data["status"] = __htmlfunc_senderror(code)
+ func_base.data["html"] = func_base.data["status"]
+ end,
+
+ #get_argument
+ function (field, default)
+ if has(func_base.header.data, "args") && has(func_base.header.data["args"], field)
+ return func_base.header.data["args"][field]
+ end
+ default
+ end,
+
+ #set cookie
+ function (field, value)
+ func_base.data["cookie"] = append(func_base.data["cookie"], [strcat(field, "=", value)])
+ end,
+
+ #get cookie
+ function (field, default)
+ if has(func_base.header.data, "Cookie") && has(func_base.header.data["Cookie"], field)
+ return func_base.header.data["Cookie"][field]
+ end
+ default
+ end,
+
+ #render
+ function (filename)
+ content = render_string(filename)
+ func_base.write(content)
+ end,
+ )
+end
+
+function __socket_callback(fd)
+ __msg = __read_header()
+ put(__eval_channel, (fd, __msg))
+end
+
+# event handler for socket input
+
+function __eval_exprs(__parsed_exprs)
+ (fd, __msg) = __parsed_exprs
+ f = nothing
+ match_route = false
+ for i = __handlers
+ m = match(i[1], __msg.path)
+ if m != nothing && m.match == __msg.path
+ match_route = true
+ f = get_func(__msg)
+ if __msg.method == "GET" && i[2].get != nothing
+ i[2].get(f)
+ elseif __msg.method == "POST" && i[2].post != nothing
+ i[2].post(f)
+ else
+ # method not allow
+ f.senderror(405)
+ end
+ break
+ end
+ end
+
+ if f != nothing && match_route
+ html = f.data["html"]
+ status = f.data["status"]
+ cookie = f.data["cookie"]
+ else
+ status = __htmlfunc_senderror(404)
+ html = status
+ cookie = nothing
+ end
+
+ __write_back(html, status, cookie)
+ __connect()
+end
+
+__ports = nothing
+__sockfd = nothing
+__connectfd = nothing
+__io = nothing
+__eval_channel = RemoteRef()
+function loop()
+ global __connectfd, __io, __port, __sockfd
+ __ports = [int16(4444)]
+ __sockfd = ccall(:open_any_tcp_port, Int32, (Ptr{Int16},), __ports)
+ if __sockfd == -1
+ # couldn't open the socket
+ println("could not open server socket on port 4444.")
+ exit()
+ end
+ println(__ports)
+ __connect()
+ add_fd_handler(__connectfd, __socket_callback)
+ while true
+ __eval_exprs(take(__eval_channel))
+ end
+end
View
100 julia_webserver_iostream.jl
@@ -0,0 +1,100 @@
+function __readline()
+ global __io
+ line = ""
+ while true
+ char = read(__io, Char)
+ if char == '\n'
+ break
+ end
+ line = strcat(line, char)
+ end
+ line
+end
+
+function __write_back(html, status, cookie)
+ global __io, __connectfd
+ write(__io, "$DEFAULT_PROTOCOL $status\n")
+ write(__io, "Server: Microsoft-IIS/5.0\n")
+ write(__io, "Content-Length: $(length(html))\n")
+ if cookie != nothing && length(cookie) > 0
+ for i = cookie
+ write(__io, "Set-Cookie: $i\n")
+ end
+ end
+ write(__io, "Content-Type: text/html; charset=UTF-8\n\n")
+
+ write(__io, "$html\n")
+ flush(__io)
+ close(__io)
+end
+
+function __connect()
+ global __connectfd, __io
+ __connectfd = ccall(:accept, Int32, (Int32, Ptr{Void}, Ptr{Void}), __sockfd, C_NULL, C_NULL)
+ __io = fdio(__connectfd, true)
+end
+
+function __read_cookie(data)
+ cookies = HashTable()
+
+ cookies
+end
+
+function __read_header()
+ line_index = 0
+ __method = DEFAULT_METHOD
+ __path = DEFAULT_PATH
+ __protocol = DEFAULT_PROTOCOL
+ __data = HashTable()
+ post_read_more_line = false
+
+ while true
+ line = __readline()
+ if length(line) <= 1
+ if post_read_more_line
+ post_read_more_line = false
+ __data["args"] = __read_arguments_from_header(__data)
+ end
+ break
+ end
+ if line_index == 0
+ m = match(r"^(\w+)\s([^\s]+)\s([^\n\r]+)", line)
+ (__method, __path, __protocol) = m.captures
+ if __method == "POST"
+ post_read_more_line = true
+ end
+ else
+ m = match(r"^([\w\-]+)\:\s([^\n\r]+)", line)
+ (key, value) = m.captures
+ if key == "Cookie"
+ local tmp = split(value, ';')
+ local cookies = HashTable()
+ for cookie_item = tmp
+ (cookie_filed, cookie_value) = match(r"^\s*(\w+)=(.*)$", cookie_item).captures
+ cookies[cookie_filed] = cookie_value
+ end
+ __data[key] = cookies
+ else
+ __data[key] = value
+ end
+ end
+ line_index += 1
+ end
+ __Header(__method, __path, __protocol, __data)
+end
+
+function __read_arguments_from_header(__data)
+ if has(__data, "Content-Length") == false || int(__data["Content-Length"]) <= 0
+ return __data
+ end
+ argstring = read(__io, Uint8, int(__data["Content-Length"]))
+ argstring = UTF8String(argstring)
+ __args = split(argstring, '&')
+ args_hash = HashTable()
+ for arg_string = __args
+ (key, value) = match(r"^([^=]+)=(.*)$", arg_string).captures
+ args_hash[key] = URLDecode(value)
+ end
+
+ args_hash
+end
View
42 julia_webserver_string.jl
@@ -0,0 +1,42 @@
+function +(str1::ASCIIString, str2::ASCIIString)
+ strcat(str1, str2)
+end
+function replace(str::ASCIIString, ch::Char, replacement::ASCIIString)
+ replace(str, Regex(UTF8String([uint8(ch)])), replacement)
+end
+
+function URLDecode(str)
+ str = replace(str, "+", "%20")
+ chars = split(str, '%')
+ if length(chars) <= 1
+ return str
+ end
+ strs = ""
+ for i=chars
+ global strs
+ if length(i) < 2
+ continue
+ end
+ strs = strcat(strs, UTF8String([hextoten(i[1:2])]), i[3:])
+ end
+ strs
+end
+
+function hextoten(num)
+ len = length(num)
+ num = uppercase(num)
+ index = 0
+ total = 0x0
+ for i=num
+ index += 1
+ count = 0
+ if int(i) <= 57
+ count = int(i) - 48
+ else
+ count = int(i) - 55
+ end
+ count = count * 16^(len-index)
+ total += count
+ end
+ convert(Uint8, total)
+end
View
215 julia_webserver_template.jl
@@ -0,0 +1,215 @@
+render_string(filename) = render_string(filename, HashTable())
+function render_string(filename, data)
+ lib = check_exist_lib(filename)
+ if lib != nothing
+ update_lib(filename)
+ end
+
+ html = get_data(filename)
+
+ if typeof(html) == typeof(has)
+ content = html(data)
+ else
+ content = render_string(html["extend"], html)
+ end
+ content
+end
+
+function addslashes(str)
+ s = str
+ #s = replace(str, r"\\", "\\\\")
+ s = replace(s, "\"", "\\\"")
+ s = replace(s, r"\$", "\\\$")
+
+ #for javascript
+ s = replace(s, "\\n", "\\\\n")
+ s = replace(s, "\\r", "\\\\r")
+ s
+end
+
+function replace_match(body, match_data::RegexMatch, replacement)
+ prefix = body[1: match_data.offset - 1]
+ tail = body[match_data.offset + length(match_data.match) :]
+ start = 1
+ while true
+ m2 = match(r"\$(\d)", replacement, start)
+ if m2 == nothing
+ break
+ end
+ start = m2.offset + 1
+ replacement = replace(replacement, m2.match, match_data.captures[int(m2.captures[1])])
+ end
+ strcat(prefix, replacement, tail)
+end
+replace_match(body, regex::Nothing, replacement) = body
+replace_match(body, regex::Regex, replacement) = replace_match(body, match(regex, body), replacement)
+
+function create_base_template(content)
+ quot = "\"\"\""
+ write_data = ""
+ current_index = 1
+ block_data = HashTable()
+ while true
+ match_block = match(r"{% block ([^\s]+) %}([^{]*){% end %}", content, current_index)
+ if match_block == nothing
+ break
+ end
+ current_index = match_block.offset + 1
+ key, value = match_block.captures
+ block_data[key] = value
+ content = replace_match(content, match_block, "\$($key)")
+ content = replace_match(content, r"{{\s(.+?)\s}}", "\$(\$1)")
+ end
+ for i = block_data
+ data = strcat(quot, i[2], quot)
+ write_data = strcat(write_data, i[1], " = has(data, \"$(i[1])\") ? data[\"$(i[1])\"] : ", data, "\n")
+ end
+ strcat(write_data, quot, content, quot, "\n")
+end
+
+function create_extend_template(match_extend, content)
+ quot = "\"\"\""
+ write_data = strcat("extend = \"", match_extend.captures[1], "\"\n")
+ current_index = 1
+ last_block_start = -1
+ last_nest_start = -1
+ last_end_start = -1
+ current_block = ""
+ return_field = []
+ level = 0
+ while true
+ match_command = match(r"{% ([^\s]+?)(?:\s(.*?))? %}", content, current_index)
+ if match_command == nothing
+ break
+ end
+ current_index = match_command.offset + 1
+ method = match_command.captures[1]
+
+ if last_block_start > 0
+ write_data = strcat(write_data, content[last_block_start: current_index - 2], quot, "\n")
+ last_block_start = -1
+ end
+
+ if last_nest_start > 0
+ write_data = strcat(write_data, make_nest_string(content, current_block, last_nest_start, current_index))
+ last_nest_start = -1
+ end
+
+ nest_method = ["for", "if", "else", "elseif"]
+ if contains(nest_method, method)
+ last_nest_start = current_index + length(match_command.match) - 1
+ elseif method == "block"
+ last_block_start = current_index + length(match_command.match) - 1
+ end
+
+ if last_end_start > 0
+ tmp_content = content[last_end_start: current_index - 2]
+ write_data = strcat(write_data, "$current_block = strcat($current_block, ", quot, tmp_content, quot, ")\n")
+ last_end_start = -1
+ end
+
+ level = get_level(method, level)
+ if level == -1 && method == "end"
+ level = 0
+ continue
+ elseif method == "end"
+ last_end_start = current_index + length(match_command.match) - 1
+ end
+
+ if method == "block"
+ current_block = match_command.captures[2]
+ return_field = append(return_field, [current_block])
+ end
+
+ write_data = strcat(write_data, get_method_data(method, match_command))
+ end
+ write_data = strcat(write_data, "\t{\"extend\"=>", "extend,")
+ for field = return_field
+ write_data = strcat(write_data, "\"$field\"=>$field,")
+ end
+ write_data = strcat(write_data, "}\n")
+end
+
+function make_nest_string(content, current_block, start, index)
+ quot = "\"\"\""
+ tmp_content = content[start: index - 2]
+ m = match(r"{{\s(.+?)\s}}", tmp_content)
+ if m != nothing
+ tmp_content = strcat(tmp_content[1:m.offset-1], "\$(", m.captures[1], ")", tmp_content[m.offset + length(m.match):])
+ end
+
+ strcat("$current_block = strcat($current_block, ", quot, tmp_content, quot, ")\n")
+end
+
+function get_level(method, level)
+ high_level_method = ["for", "if"]
+ if contains(high_level_method, method)
+ level += 1
+ elseif method == "end"
+ if level <= 0
+ level = -1
+ else
+ level -= 1
+ end
+ end
+ level
+end
+
+function get_method_data(method, match_command)
+ quot = "\"\"\""
+ if method == "block"
+ return strcat(match_command.captures[2] , " = ", quot)
+ elseif contains(["end", "else"], method)
+ return strcat(method , "\n")
+ elseif contains(["for", "if", "elseif"], method)
+ return strcat(method, " ", match_command.captures[2], "\n")
+ end
+ return ""
+end
+
+function update_lib(filename)
+ quot = "\"\"\""
+ stream = open(strcat("./tpl/", filename, ".html"))
+ content = addslashes(readall(stream))
+ write_data = ""
+ match_extend = match(r"{% extend ([^\s]+) %}", content)
+ write_data = strcat(write_data, "is_extend = ", match_extend == nothing ? "false" : "true", "\n")
+ write_data = strcat(write_data, "function html(", match_extend == nothing ? "data" : "",")\n")
+ if match_extend == nothing
+ write_data = strcat(write_data, create_base_template(content))
+ else
+ write_data = strcat(write_data, create_extend_template(match_extend, content))
+ end
+ write_data = strcat(write_data, "end")
+ write_data = UTF8String(write_data.data)
+ filename = replace(filename, "/", "_")
+ stream = open(strcat("./cache/", filename, "_tpl.j"), "w")
+ write(stream, write_data)
+ flush(stream)
+end
+
+function check_exist_lib(filename)
+ file_path = strcat("./tpl/", filename, ".html")
+ if DEBUG
+ return false
+ end
+ try
+ s = open(file_path)
+ return true
+ catch x
+ return true
+ end
+ false
+end
+
+function get_data(filename)
+ begin
+ filename = replace(filename, "/", "_")
+ load(strcat("./cache/", filename, "_tpl.j"))
+ if is_extend
+ return html()
+ else
+ return html
+ end
+ end
+end
View
22 julia_webserver_type.jl
@@ -0,0 +1,22 @@
+type __Header
+ method::String
+ path::String
+ protocol::String
+ data::HashTable
+end
+
+type Func
+ data::HashTable
+ header::__Header
+ write::Function
+ senderror::Function
+ get_argument::Function
+ set_cookie::Function
+ get_cookie::Function
+ render::Function
+end
+
+type Handler
+ get::Union(Function, Nothing)
+ post::Union(Function, Nothing)
+end

0 comments on commit 9e2cea5

Please sign in to comment.
Something went wrong with that request. Please try again.