1-- needs Alias from /home/c/diego/tec/luasocket/test to 2-- "/luasocket-test" and "/luasocket-test/" 3-- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi 4-- to "/luasocket-test-cgi" and "/luasocket-test-cgi/" 5-- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth 6local socket = require("socket") 7local http = require("socket.http") 8local url = require("socket.url") 9 10local mime = require("mime") 11local ltn12 = require("ltn12") 12 13-- override protection to make sure we see all errors 14-- socket.protect = function(s) return s end 15 16dofile("testsupport.lua") 17 18local host, proxy, request, response, index_file 19local ignore, expect, index, prefix, cgiprefix, index_crlf 20 21http.TIMEOUT = 10 22 23local t = socket.gettime() 24 25--host = host or "diego.student.princeton.edu" 26--host = host or "diego.student.princeton.edu" 27host = host or "localhost" 28proxy = proxy or "http://localhost:3128" 29prefix = prefix or "/luasocket-test" 30cgiprefix = cgiprefix or "/luasocket-test-cgi" 31index_file = "index.html" 32 33-- read index with CRLF convention 34index = readfile(index_file) 35 36local check_result = function(response, expect, ignore) 37 for i,v in pairs(response) do 38 if not ignore[i] then 39 if v ~= expect[i] then 40 local f = io.open("err", "w") 41 f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i])) 42 f:close() 43 fail(i .. " differs!") 44 end 45 end 46 end 47 for i,v in pairs(expect) do 48 if not ignore[i] then 49 if v ~= response[i] then 50 local f = io.open("err", "w") 51 f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v)) 52 v = string.sub(type(v) == "string" and v or "", 1, 70) 53 f:close() 54 fail(i .. " differs!") 55 end 56 end 57 end 58 print("ok") 59end 60 61local check_request = function(request, expect, ignore) 62 local t 63 if not request.sink then request.sink, t = ltn12.sink.table() end 64 request.source = request.source or 65 (request.body and ltn12.source.string(request.body)) 66 local response = {} 67 response.code, response.headers, response.status = 68 socket.skip(1, http.request(request)) 69 if t and #t > 0 then response.body = table.concat(t) end 70 check_result(response, expect, ignore) 71end 72 73------------------------------------------------------------------------ 74io.write("testing request uri correctness: ") 75local forth = cgiprefix .. "/request-uri?" .. "this+is+the+query+string" 76local back, c, h = http.request("http://" .. host .. forth) 77if not back then fail(c) end 78back = url.parse(back) 79if similar(back.query, "this+is+the+query+string") then print("ok") 80else fail(back.query) end 81 82------------------------------------------------------------------------ 83io.write("testing query string correctness: ") 84forth = "this+is+the+query+string" 85back = http.request("http://" .. host .. cgiprefix .. 86 "/query-string?" .. forth) 87if similar(back, forth) then print("ok") 88else fail("failed!") end 89 90------------------------------------------------------------------------ 91io.write("testing document retrieval: ") 92request = { 93 url = "http://" .. host .. prefix .. "/index.html" 94} 95expect = { 96 body = index, 97 code = 200 98} 99ignore = { 100 status = 1, 101 headers = 1 102} 103check_request(request, expect, ignore) 104 105------------------------------------------------------------------------ 106io.write("testing redirect loop: ") 107request = { 108 url = "http://" .. host .. cgiprefix .. "/redirect-loop" 109} 110expect = { 111 code = 302 112} 113ignore = { 114 status = 1, 115 headers = 1, 116 body = 1 117} 118check_request(request, expect, ignore) 119 120------------------------------------------------------------------------ 121io.write("testing invalid url: ") 122local r, e = http.request{url = host .. prefix} 123assert(r == nil and e == "invalid host ''") 124r, re = http.request(host .. prefix) 125assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) .. 126 " vs " .. tostring(e)) 127print("ok") 128 129io.write("testing invalid empty port: ") 130request = { 131 url = "http://" .. host .. ":" .. prefix .. "/index.html" 132} 133expect = { 134 body = index, 135 code = 200 136} 137ignore = { 138 status = 1, 139 headers = 1 140} 141check_request(request, expect, ignore) 142 143------------------------------------------------------------------------ 144io.write("testing post method: ") 145-- wanted to test chunked post, but apache doesn't support it... 146request = { 147 url = "http://" .. host .. cgiprefix .. "/cat", 148 method = "POST", 149 body = index, 150 -- remove content-length header to send chunked body 151 headers = { ["content-length"] = string.len(index) } 152} 153expect = { 154 body = index, 155 code = 200 156} 157ignore = { 158 status = 1, 159 headers = 1 160} 161check_request(request, expect, ignore) 162 163------------------------------------------------------------------------ 164--[[ 165io.write("testing proxy with post method: ") 166request = { 167 url = "http://" .. host .. cgiprefix .. "/cat", 168 method = "POST", 169 body = index, 170 headers = { ["content-length"] = string.len(index) }, 171 proxy= proxy 172} 173expect = { 174 body = index, 175 code = 200 176} 177ignore = { 178 status = 1, 179 headers = 1 180} 181check_request(request, expect, ignore) 182]] 183 184------------------------------------------------------------------------ 185io.write("testing simple post function: ") 186back = http.request("http://" .. host .. cgiprefix .. "/cat", index) 187assert(back == index) 188print("ok") 189 190------------------------------------------------------------------------ 191io.write("testing ltn12.(sink|source).file: ") 192request = { 193 url = "http://" .. host .. cgiprefix .. "/cat", 194 method = "POST", 195 source = ltn12.source.file(io.open(index_file, "rb")), 196 sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")), 197 headers = { ["content-length"] = string.len(index) } 198} 199expect = { 200 code = 200 201} 202ignore = { 203 status = 1, 204 headers = 1 205} 206check_request(request, expect, ignore) 207back = readfile(index_file .. "-back") 208assert(back == index) 209os.remove(index_file .. "-back") 210 211------------------------------------------------------------------------ 212io.write("testing ltn12.(sink|source).chain and mime.(encode|decode): ") 213 214local function b64length(len) 215 local a = math.ceil(len/3)*4 216 local l = math.ceil(a/76) 217 return a + l*2 218end 219 220local source = ltn12.source.chain( 221 ltn12.source.file(io.open(index_file, "rb")), 222 ltn12.filter.chain( 223 mime.encode("base64"), 224 mime.wrap("base64") 225 ) 226) 227 228local sink = ltn12.sink.chain( 229 mime.decode("base64"), 230 ltn12.sink.file(io.open(index_file .. "-back", "wb")) 231) 232 233request = { 234 url = "http://" .. host .. cgiprefix .. "/cat", 235 method = "POST", 236 source = source, 237 sink = sink, 238 headers = { ["content-length"] = b64length(string.len(index)) } 239} 240expect = { 241 code = 200 242} 243ignore = { 244 body_cb = 1, 245 status = 1, 246 headers = 1 247} 248check_request(request, expect, ignore) 249back = readfile(index_file .. "-back") 250assert(back == index) 251os.remove(index_file .. "-back") 252 253------------------------------------------------------------------------ 254io.write("testing http redirection: ") 255request = { 256 url = "http://" .. host .. prefix 257} 258expect = { 259 body = index, 260 code = 200 261} 262ignore = { 263 status = 1, 264 headers = 1 265} 266check_request(request, expect, ignore) 267 268------------------------------------------------------------------------ 269--[[ 270io.write("testing proxy with redirection: ") 271request = { 272 url = "http://" .. host .. prefix, 273 proxy = proxy 274} 275expect = { 276 body = index, 277 code = 200 278} 279ignore = { 280 status = 1, 281 headers = 1 282} 283check_request(request, expect, ignore) 284]] 285 286------------------------------------------------------------------------ 287io.write("testing automatic auth failure: ") 288request = { 289 url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html" 290} 291expect = { 292 code = 401 293} 294ignore = { 295 body = 1, 296 status = 1, 297 headers = 1 298} 299check_request(request, expect, ignore) 300 301------------------------------------------------------------------------ 302io.write("testing http redirection failure: ") 303request = { 304 url = "http://" .. host .. prefix, 305 redirect = false 306} 307expect = { 308 code = 301 309} 310ignore = { 311 body = 1, 312 status = 1, 313 headers = 1 314} 315check_request(request, expect, ignore) 316 317------------------------------------------------------------------------ 318io.write("testing document not found: ") 319request = { 320 url = "http://" .. host .. "/wrongdocument.html" 321} 322expect = { 323 code = 404 324} 325ignore = { 326 body = 1, 327 status = 1, 328 headers = 1 329} 330check_request(request, expect, ignore) 331 332------------------------------------------------------------------------ 333io.write("testing auth failure: ") 334request = { 335 url = "http://" .. host .. prefix .. "/auth/index.html" 336} 337expect = { 338 code = 401 339} 340ignore = { 341 body = 1, 342 status = 1, 343 headers = 1 344} 345check_request(request, expect, ignore) 346 347------------------------------------------------------------------------ 348io.write("testing manual basic auth: ") 349request = { 350 url = "http://" .. host .. prefix .. "/auth/index.html", 351 headers = { 352 authorization = "Basic " .. (mime.b64("luasocket:password")) 353 } 354} 355expect = { 356 code = 200, 357 body = index 358} 359ignore = { 360 status = 1, 361 headers = 1 362} 363check_request(request, expect, ignore) 364 365------------------------------------------------------------------------ 366io.write("testing automatic basic auth: ") 367request = { 368 url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html" 369} 370expect = { 371 code = 200, 372 body = index 373} 374ignore = { 375 status = 1, 376 headers = 1 377} 378check_request(request, expect, ignore) 379 380------------------------------------------------------------------------ 381io.write("testing auth info overriding: ") 382request = { 383 url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html", 384 user = "luasocket", 385 password = "password" 386} 387expect = { 388 code = 200, 389 body = index 390} 391ignore = { 392 status = 1, 393 headers = 1 394} 395check_request(request, expect, ignore) 396 397------------------------------------------------------------------------ 398io.write("testing cgi output retrieval (probably chunked...): ") 399request = { 400 url = "http://" .. host .. cgiprefix .. "/cat-index-html" 401} 402expect = { 403 body = index, 404 code = 200 405} 406ignore = { 407 status = 1, 408 headers = 1 409} 410check_request(request, expect, ignore) 411 412------------------------------------------------------------------------ 413local body 414io.write("testing simple request function: ") 415body = http.request("http://" .. host .. prefix .. "/index.html") 416assert(body == index) 417print("ok") 418 419------------------------------------------------------------------------ 420io.write("testing HEAD method: ") 421local r, c, h = http.request { 422 method = "HEAD", 423 url = "http://www.tecgraf.puc-rio.br/~diego/" 424} 425assert(r and h and (c == 200), c) 426print("ok") 427 428------------------------------------------------------------------------ 429io.write("testing host not found: ") 430local c, e = socket.connect("example.invalid", 80) 431local r, re = http.request{url = "http://example.invalid/does/not/exist"} 432assert(r == nil and e == re, tostring(r) .. " " .. tostring(re)) 433r, re = http.request("http://example.invalid/does/not/exist") 434assert(r == nil and e == re) 435print("ok") 436 437------------------------------------------------------------------------ 438print("passed all tests") 439os.remove("err") 440 441print(string.format("done in %.2fs", socket.gettime() - t)) 442