view src/luan/modules/http/Http.luan @ 1156:3839ecc130ea

cookie fixes
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 04 Feb 2018 23:18:51 -0700
parents bbad9a21277c
children 267fdf5e9fbd
line wrap: on
line source

java()
local Luan = require "luan:Luan.luan"
local error = Luan.error
local ipairs = Luan.ipairs or error()
local pairs = Luan.pairs or error()
local set_metatable = Luan.set_metatable or error()
local type = Luan.type or error()
local Io = require "luan:Io.luan"
local Html = require "luan:Html.luan"
local url_encode = Html.url_encode or error()
local Table = require "luan:Table.luan"
local clear = Table.clear or error()
local Package = require "luan:Package.luan"
local String = require "luan:String.luan"
local matches = String.matches or error()
local Implementation = require "luan:http/Implementation.luan"
local HttpServicer = require(Implementation.java.."HttpServicer")
local IoLuan = require "java:luan.modules.IoLuan"


local Http = {}

local function sent_error(_,_,_)
	error "headers are not accessible after you start writing content"
end

local sent_error_metatable = { __index=sent_error, __new_index=sent_error }

function Http.sent_headers(headers)
	clear(headers)
	set_metatable(headers,sent_error_metatable)
end


local function new_common(this)
	this = this or {}
	this.headers = {}
	return this
end

local function to_list(input)
	return type(input) == "table" and input or {input}
end


function Http.new_request(this)
	this = new_common(this)
	this.method = "GET"  -- default
	-- this.path
	-- this.protocol
	this.scheme = "http"  -- default
	this.port = 80  -- default
	this.parameters = {}
	this.cookies = {}

	function this.query_string()
		local string_uri = Io.uri "string:"
		local out = string_uri.text_writer()
		local and_char = ""
		for name, values in pairs(this.parameters) do
			for _, value in ipairs(to_list(values)) do
				out.write( and_char, url_encode(name), "=", url_encode(value) )
				and_char = "&"
			end
		end
		out.close()
		local s = string_uri.read_text()
		return s ~= "" and s or nil
	end

	function this.url()
		local url = this.scheme.."://"..this.headers["host"]..this.path
		if this.method ~= "POST" then
			local query = this.query_string()
			if query ~= nil then
				url = url.."?"..query
			end
		end
		return url
	end

	return this
end

local STATUS = {
	OK = 200
	MOVED_PERMANENTLY = 301
	-- add more as needed
}
Http.STATUS = STATUS

function Http.new_response(this)
	this = new_common(this)
	this.status = STATUS.OK
	if this.java ~= nil then
		this.send_redirect = this.java.sendRedirect
		this.send_error = this.java.sendError

		function this.set_cookie(name,value,attributes)
			HttpServicer.setCookie(Http.request.java,this.java,name,value,attributes)
		end

		function this.set_persistent_cookie(name,value,attributes)
			attributes = attributes or {}
			attributes["Max-Age"] = "10000000"
			this.set_cookie(name,value,attributes)
		end

		function this.remove_cookie(name,attributes)
			attributes = attributes or {}
			attributes["Max-Age"] = "0"
			this.set_cookie(name,"delete",attributes)
		end

		function this.set()
			HttpServicer.setResponse(this,this.java)
			Http.sent_headers(this.headers)
		end

		function this.text_writer()
			this.java.setCharacterEncoding "UTF-8"
			this.java.setContentType "text/html; charset=UTF-8"
			this.set()
			return IoLuan.textWriter(this.java.getWriter())
		end

		function this.binary_writer()
			this.set()
			return IoLuan.binaryWriter(this.java.getOutputStream())
		end

		function this.reset()
			this.java.reset()
			set_metatable(this.headers,nil)
		end
	end
	return this
end

-- request = new_request{}  -- filled in by HttpServicer
-- response = new_response{}  -- filled in by HttpServicer


Http.per_session_pages = {}

function Http.per_session(page)
	Http.per_session_pages[page] = true
end

function Http.clear_session()
	Http.request.java.getSession().removeAttribute("luan")
end


function Http.uncache_site()
	for k in pairs(Table.copy(Package.loaded)) do
		if matches(k,"^site:") then
			Package.loaded[k] = nil
		end
	end
end

return Http