From af047c6e9cda7dd92590260e413522353215bf2d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 13 Jun 2023 03:01:24 +0000 Subject: CTAN sync 202306130301 --- macros/luatex/latex/luahttp/README.md | 2 +- macros/luatex/latex/luahttp/display.lua | 278 ------------------------ macros/luatex/latex/luahttp/fetch.lua | 199 ----------------- macros/luatex/latex/luahttp/luahttp-display.lua | 278 ++++++++++++++++++++++++ macros/luatex/latex/luahttp/luahttp-doc.pdf | Bin 132528 -> 135232 bytes macros/luatex/latex/luahttp/luahttp-doc.tex | 1 + macros/luatex/latex/luahttp/luahttp-fetch.lua | 199 +++++++++++++++++ macros/luatex/latex/luahttp/luahttp.sty | 4 +- 8 files changed, 481 insertions(+), 480 deletions(-) delete mode 100644 macros/luatex/latex/luahttp/display.lua delete mode 100644 macros/luatex/latex/luahttp/fetch.lua create mode 100644 macros/luatex/latex/luahttp/luahttp-display.lua create mode 100644 macros/luatex/latex/luahttp/luahttp-fetch.lua (limited to 'macros/luatex/latex') diff --git a/macros/luatex/latex/luahttp/README.md b/macros/luatex/latex/luahttp/README.md index 563992c77a..e1a144bccf 100644 --- a/macros/luatex/latex/luahttp/README.md +++ b/macros/luatex/latex/luahttp/README.md @@ -1,5 +1,5 @@ # README for LUAHTTP -Version 1.0 +Version 1.0.1 ## INTRODUCTION This is a small package that provides five commands to make HTTP requests using Lua and LuaTeX. Functionalities include API calls, fetching RSS feeds and the possibility to include images using a link. These commands run during the compilation of the PDF-Document and may require user interaction. diff --git a/macros/luatex/latex/luahttp/display.lua b/macros/luatex/latex/luahttp/display.lua deleted file mode 100644 index f7c25f7349..0000000000 --- a/macros/luatex/latex/luahttp/display.lua +++ /dev/null @@ -1,278 +0,0 @@ ---[[ --- This module is part of the LuaHTTP package --- The purpose of this module is to correctly display the data reveived from the fetch module. -]] - -local moduleName = display -local M = {} - ----------- Dependencies ------------------------ -local fetch = require("fetch") - ----------- Local variables --------------------- -local tmp_image_counter = 0 -- Counter for image names - ----------- Helper functions -------------------- - ---- Displays an image using LuaTeX img.write function. --- The image has to be saved first in order to be written to the PDF-Document using LuaTeX. --- @param data image data --- @param width optional width in cm --- @param height optional height in cm --- @see search_and_escape -local function display_image(data, width, height) - local tmp_image_name = '/tmp/tmp_image' -- filename of image saved temporarly - tmp_image_name = tmp_image_name .. tmp_image_counter - - local width = width or nil - local height = height or nil - local f = assert(io.open(tmp_image_name, 'wb')) - f:write(data) - f:close() - - -- LuaTeX does not provide built-in image scaling functions - local image = img.new({filename = tmp_image_name, width = width, height = height}) - if image then - img.write(image) - tmp_image_counter = tmp_image_counter + 1 - end -end - ---- Prompts the user to display an image. --- If an image-URL is detected the user is asked to display the image or the plain URL. --- @see is_image_url -local function prompt_user() - while true do - print("Do you want to display the image? (y/n)") - local answer = io.read() - - if answer == 'y' then - return true - elseif answer == 'n' then - return false - else - print("Invalid answer. Please enter 'y' or 'n'.") - end - end -end - ---- Searches the given URL for image extensions. --- @param url some URL --- @return true if an image extension was found, false otherwise --- @see search_and_escape -local function is_image_url(url) - local image_extensions = { "jpg", "jpeg", "png", "gif" } - for _, ext in ipairs(image_extensions) do - if string.match(url, "%." .. ext) then - return true - end - end - return false -end - ---- Searches the given value for special characters that cause problems in LaTeX-Documents. --- @param value single value of a table --- @return if no special characters where found the value is retured unchanged, --- if special characters where found the escaped value is returned, --- if an image-URL is detected and the user chooses to display that image nil is returned --- @see is_image_url, prompt_user -local function search_and_escape(value) - local value = tostring(value) - if string.find(value, "^http") then - if is_image_url(value) then - print("\nLooks like this URL leads to an image: " .. value) - if prompt_user() then - local body = fetch.image(value) - display_image(body, "5cm") - return nil - else - print("\nEscaping URL: " .. value) - value = [[\url{]] .. value .. [[}]] - end - else - print("\nEscaping URL: " .. value) - value = [[\url{]] .. value .. [[}]] - end - else - local latex_special_chars = '([%%$%{%}&%#_%^%~])' - value = value:gsub(latex_special_chars, "\\%1") - end - return value -end - ---- Prints a table to stdout. --- @param t tagle to print --- @param indent optional string used for indents -local function print_table(t, indent) - indent = indent or "" - for k, v in pairs(t) do - if type(v) == "table" then - print(indent .. k .. ":") - print_table(v, indent .. " ") - else - print(indent .. k .. ": " .. tostring(v)) - end - end -end - ---- Converts a table to text which can be written to the PDF-Document --- The values of the table are first searched for special characters. --- @param tbl table to be converted --- @return text --- @see search_and_escape -local function table_to_text(tbl) - local results = {} - for k, v in pairs(tbl) do - if type(v) == "table" then - table.insert(results, table_to_text(v)) - else - v = search_and_escape(v) - if v then - table.insert(results, v .. " \\\\ ") - end - end - end - return table.concat(results, " \\ ") -end - ---- Check if a table contains a certain value. --- @param table input table --- @param target_value value to be searched --- @return true if value was found, false otherwise -local function table_contains(table, target_value) - for _, value in pairs(table) do - if type(value) == "table" then - table_contains(value, target_value) - elseif value == target_value then - return true - end - end - return false -end - ---- Filter out table entries that are not in the provided target keys. --- @param input_table --- @param target_keys array of target keys --- @param results used for recursion --- @return return a new table containing only the target keys and their values -local function filter_table(input_table, target_keys, results) - local results = results or {} - - for _, target_key in ipairs(target_keys) do - for key, value in pairs(input_table) do - if type(value) == "table" then - filter_table(value, target_keys, results) - elseif tostring(key) == target_key then - if not table_contains(results, value) then - table.insert(results, value) - break - end - end - end - end - return results -end - ---- Converts a string containing a comma seperated list of elements to an array (ipairs). --- @param str input string --- @return table containing the elements as values -local function string_to_ipairs(str) - local t = {} - for value in string.gmatch(str, "([^,]+)") do - table.insert(t, value) - end - return t -end - ----------- Module functions -------------------- - ---- Reads the contents of a JSON-file, filters the response and prints the result to the PDF-Document. --- @param json_file_path path to the JSON-file --- @param keys optional keys to filter out the relevant values from the response -function M.json_using_file(json_file_path, keys) - local data = fetch.json_using_file(json_file_path) - print_table(data) - if keys then - local keys = string_to_ipairs(tostring(keys)) - local values = filter_table(data, keys) - tex.sprint(table_to_text(values)) - else - tex.sprint(table_to_text(data)) - end -end - ---- Prints the response filtered by the keys to the PDF-Document. --- @param url URL of the API --- @param keys optional keys to filter out the relevant values from the response -function M.json(url, keys) - local data = fetch.json(tostring(url)) - print_table(data) - if keys then - local keys = string_to_ipairs(tostring(keys)) - local values = filter_table(data, keys) - tex.sprint(table_to_text(values)) - else - tex.sprint(table_to_text(data)) - end -end - ---- Print an image to the PDF-Document. --- @param url URL of the image --- @param width optional width in cm --- @param height optional height in cm -function M.image(url, width, height) - local data = fetch.image(tostring(url)) - display_image(data, width, height) -end - ---- Print values from an rss-feed to the PDF-Document. --- @param url URL of the feed --- @param limit limits the amount of entries that get printed to the PDF-Document --- @param feed_info_keys keys used to filter the feed information --- @param entry_keys keys used to filter the feed entries -function M.rss(url, limit, feed_info_keys, entry_keys) - local data = fetch.rss(tostring(url)) - - if feed_info_keys then - local feed_info_keys = string_to_ipairs(tostring(feed_info_keys)) - local feed = data.feed - local feed_info_filtered = filter_table(feed, feed_info_keys) - - tex.sprint(table_to_text(feed_info_filtered)) - end - - local entries = {} - - for i = 1, limit do - if data.entries[i] then - table.insert(entries, data.entries[i]) - end - end - - if entry_keys then - local entry_keys = string_to_ipairs(tostring(entry_keys)) - local entries_filtered = filter_table(entries, entry_keys) - - print_table(entries_filtered) - tex.sprint(table_to_text(entries_filtered)) - else - tex.sprint(table_to_text(entries)) - end -end - ---- Print the reponse from a request using query parameters to the PDF-Document. --- @param url URL of the API --- @param keys keys to filter out the relevant values --- @param ... multiple optional query parameters used in the request -function M.json_using_query(url, keys, ...) - local query_parameters = { ... } - local data = fetch.json_using_query(url, query_parameters) - - print_table(data) - - local keys = string_to_ipairs(tostring(keys)) - local values = filter_table(data, keys) - tex.sprint(table_to_text(values)) -end - -return M diff --git a/macros/luatex/latex/luahttp/fetch.lua b/macros/luatex/latex/luahttp/fetch.lua deleted file mode 100644 index c39997173d..0000000000 --- a/macros/luatex/latex/luahttp/fetch.lua +++ /dev/null @@ -1,199 +0,0 @@ ---[[ --- This module is part of the LuaHTTP package --- The purpose of this module is to make HTTP requests and return the response. --- --- Dependencies: --- dkjson --- luasec --- ltn12 --- feedparser -]] - -local moduleName = fetch -local M = {} - ----------- Dependencies ------------------------ -local http = require("socket.http") -local urlsocket = require("socket.url") -local https = require("ssl.https") -local dkjson = require("dkjson") -local ltn12 = require("ltn12") -local feedparser = require("feedparser") - ----------- Local variables --------------------- - ----------- Helper functions -------------------- - ---- Makes an HTTP request using the provided request parameter. --- @param request table containing the request parameters --- @return the response as a table -local function http_request(request) - local url = request.url - print("\nConnecting to " .. url) - - -- Detect HTTPS - local client = http - if url:lower():find("^https://") then - client = https - end - - -- Save optional body - local body = request.body - - -- Prepare request - local response = {} - local request = { - method = request.method or "GET", - url = url, - headers = request.headers or nil, - redirect = request.redirect or false, - sink = ltn12.sink.table(response) - } - - -- Send optional body - if body then - if type(body) == "table" then - body = dkjson.encode(body) - end - request.source = ltn12.source.string(body) - request.headers["Content-Length"] = #body - end - - -- Make the request - local response_status, response_code, response_header, response_message = client.request(request) - - local message = response_message or "(No response message recieved)" - - if response_status == nil then - error("\n!!! Error connecting to " .. url .. "\nResponse: " .. response_code .. "\nMessage: " .. message) - end - - -- Check for redirects and return body - if response_code == 301 or response_code == 302 or response_code == 303 then - print("\nResponse " .. message) - local redirect_url = response_header["location"] - if redirect_url == url then - error("\n!!! Error connecting to " .. url .. " results in a redirection loop") - else - print("\n!! Warning: redirecting to " .. redirect_url) - request.url = redirect_url - return http_request(request) - end - elseif response_code == 200 then - print("\nResponse " .. message) - if response == null or not next(response) then - error("\n!!! Error empty response") - end - return response - else - error("\n!!! Error connecting to " .. url .. "\nResponse: " .. response_code .. "\nMessage: " .. message) - end -end - ---- Parse the given JSON-file. --- @param file_path path to JSON-file --- @return table containing the JSON data -local function parse_json_file(file_path) - local file = io.open(file_path, "r") - local content = file:read("*all") - file:close() - return dkjson.decode(content) -end - ---- Split a given string on the first occurence of a given character. --- @param str string containing the given character --- @param char target character at which the string gets split --- @return table containing the first part of the string as the key and the second part as the value -local function split_first(str, char) - local result = {} - local pos = str:find(char) - local key = str:sub(1, pos - 1) - local value = str:sub(pos + 1) - result[key] = value - return result -end - ----------- Module functions -------------------- - ---- Make a GET request using the provided URL --- @param url target URL --- @return table containg the response -function M.json(url) - local request = { - method = "GET", - url = url, - headers = { - ["Accept"] = "application/json" - }, - } - local response = http_request(request) - return dkjson.decode(table.concat(response)) -end - ---- Make a request using the provided JSON-file --- @param json_file_path path to JSON-file --- @return table containg the response -function M.json_using_file(json_file_path) - print("\nUsing file " .. json_file_path) - local request = parse_json_file(json_file_path) - local response = http_request(request) - return dkjson.decode(table.concat(response)) -end - ---- Make a GET request using the provided URL --- @param url target URL --- @return table containg the response -function M.rss(url) - local request = { - method = "GET", - url = url, - headers = { - ["Accept"] = "application/rss+xml" - }, - } - local response = http_request(request) - return feedparser.parse(table.concat(response)) -end - ---- Fetch image data using the provided URL --- @param url target URL leading to an image --- @return image data -function M.image(url) - local request = { - method = "GET", - url = url - } - local response = http_request(request) - return table.concat(response) -end - ---- Make a POST request using the provided URL and query parameters --- @param url target URL --- @param query_parameters parameters sent in the URL --- @return table containg the response -function M.json_using_query(url, query_parameters) - local url = url - for _, value in ipairs(query_parameters) do - local params = split_first(value, "=") - for k, v in pairs(params) do - v = string.gsub(v, "\n", "") - url = url .. k .. "=" .. urlsocket.escape(v) - end - end - - print("\nURL: " .. url) - - local request = { - method = "POST", - url = url, - headers = { - ["Accept"] = "application/json", - ["Content-Type"] = "application/x-www-form-urlencoded"; - }, - redirect = false - } - local response = http_request(request) - return dkjson.decode(table.concat(response)) -end - -return M diff --git a/macros/luatex/latex/luahttp/luahttp-display.lua b/macros/luatex/latex/luahttp/luahttp-display.lua new file mode 100644 index 0000000000..1a41cfb22c --- /dev/null +++ b/macros/luatex/latex/luahttp/luahttp-display.lua @@ -0,0 +1,278 @@ +--[[ +-- This module is part of the LuaHTTP package +-- The purpose of this module is to correctly display the data reveived from the fetch module. +]] + +local moduleName = display +local M = {} + +---------- Dependencies ------------------------ +local fetch = require("luahttp-fetch") + +---------- Local variables --------------------- +local tmp_image_counter = 0 -- Counter for image names + +---------- Helper functions -------------------- + +--- Displays an image using LuaTeX img.write function. +-- The image has to be saved first in order to be written to the PDF-Document using LuaTeX. +-- @param data image data +-- @param width optional width in cm +-- @param height optional height in cm +-- @see search_and_escape +local function display_image(data, width, height) + local tmp_image_name = '/tmp/tmp_image' -- filename of image saved temporarly + tmp_image_name = tmp_image_name .. tmp_image_counter + + local width = width or nil + local height = height or nil + local f = assert(io.open(tmp_image_name, 'wb')) + f:write(data) + f:close() + + -- LuaTeX does not provide built-in image scaling functions + local image = img.new({filename = tmp_image_name, width = width, height = height}) + if image then + img.write(image) + tmp_image_counter = tmp_image_counter + 1 + end +end + +--- Prompts the user to display an image. +-- If an image-URL is detected the user is asked to display the image or the plain URL. +-- @see is_image_url +local function prompt_user() + while true do + print("Do you want to display the image? (y/n)") + local answer = io.read() + + if answer == 'y' then + return true + elseif answer == 'n' then + return false + else + print("Invalid answer. Please enter 'y' or 'n'.") + end + end +end + +--- Searches the given URL for image extensions. +-- @param url some URL +-- @return true if an image extension was found, false otherwise +-- @see search_and_escape +local function is_image_url(url) + local image_extensions = { "jpg", "jpeg", "png", "gif" } + for _, ext in ipairs(image_extensions) do + if string.match(url, "%." .. ext) then + return true + end + end + return false +end + +--- Searches the given value for special characters that cause problems in LaTeX-Documents. +-- @param value single value of a table +-- @return if no special characters where found the value is retured unchanged, +-- if special characters where found the escaped value is returned, +-- if an image-URL is detected and the user chooses to display that image nil is returned +-- @see is_image_url, prompt_user +local function search_and_escape(value) + local value = tostring(value) + if string.find(value, "^http") then + if is_image_url(value) then + print("\nLooks like this URL leads to an image: " .. value) + if prompt_user() then + local body = fetch.image(value) + display_image(body, "5cm") + return nil + else + print("\nEscaping URL: " .. value) + value = [[\url{]] .. value .. [[}]] + end + else + print("\nEscaping URL: " .. value) + value = [[\url{]] .. value .. [[}]] + end + else + local latex_special_chars = '([%%$%{%}&%#_%^%~])' + value = value:gsub(latex_special_chars, "\\%1") + end + return value +end + +--- Prints a table to stdout. +-- @param t tagle to print +-- @param indent optional string used for indents +local function print_table(t, indent) + indent = indent or "" + for k, v in pairs(t) do + if type(v) == "table" then + print(indent .. k .. ":") + print_table(v, indent .. " ") + else + print(indent .. k .. ": " .. tostring(v)) + end + end +end + +--- Converts a table to text which can be written to the PDF-Document +-- The values of the table are first searched for special characters. +-- @param tbl table to be converted +-- @return text +-- @see search_and_escape +local function table_to_text(tbl) + local results = {} + for k, v in pairs(tbl) do + if type(v) == "table" then + table.insert(results, table_to_text(v)) + else + v = search_and_escape(v) + if v then + table.insert(results, v .. " \\\\ ") + end + end + end + return table.concat(results, " \\ ") +end + +--- Check if a table contains a certain value. +-- @param table input table +-- @param target_value value to be searched +-- @return true if value was found, false otherwise +local function table_contains(table, target_value) + for _, value in pairs(table) do + if type(value) == "table" then + table_contains(value, target_value) + elseif value == target_value then + return true + end + end + return false +end + +--- Filter out table entries that are not in the provided target keys. +-- @param input_table +-- @param target_keys array of target keys +-- @param results used for recursion +-- @return return a new table containing only the target keys and their values +local function filter_table(input_table, target_keys, results) + local results = results or {} + + for _, target_key in ipairs(target_keys) do + for key, value in pairs(input_table) do + if type(value) == "table" then + filter_table(value, target_keys, results) + elseif tostring(key) == target_key then + if not table_contains(results, value) then + table.insert(results, value) + break + end + end + end + end + return results +end + +--- Converts a string containing a comma seperated list of elements to an array (ipairs). +-- @param str input string +-- @return table containing the elements as values +local function string_to_ipairs(str) + local t = {} + for value in string.gmatch(str, "([^,]+)") do + table.insert(t, value) + end + return t +end + +---------- Module functions -------------------- + +--- Reads the contents of a JSON-file, filters the response and prints the result to the PDF-Document. +-- @param json_file_path path to the JSON-file +-- @param keys optional keys to filter out the relevant values from the response +function M.json_using_file(json_file_path, keys) + local data = fetch.json_using_file(json_file_path) + print_table(data) + if keys then + local keys = string_to_ipairs(tostring(keys)) + local values = filter_table(data, keys) + tex.sprint(table_to_text(values)) + else + tex.sprint(table_to_text(data)) + end +end + +--- Prints the response filtered by the keys to the PDF-Document. +-- @param url URL of the API +-- @param keys optional keys to filter out the relevant values from the response +function M.json(url, keys) + local data = fetch.json(tostring(url)) + print_table(data) + if keys then + local keys = string_to_ipairs(tostring(keys)) + local values = filter_table(data, keys) + tex.sprint(table_to_text(values)) + else + tex.sprint(table_to_text(data)) + end +end + +--- Print an image to the PDF-Document. +-- @param url URL of the image +-- @param width optional width in cm +-- @param height optional height in cm +function M.image(url, width, height) + local data = fetch.image(tostring(url)) + display_image(data, width, height) +end + +--- Print values from an rss-feed to the PDF-Document. +-- @param url URL of the feed +-- @param limit limits the amount of entries that get printed to the PDF-Document +-- @param feed_info_keys keys used to filter the feed information +-- @param entry_keys keys used to filter the feed entries +function M.rss(url, limit, feed_info_keys, entry_keys) + local data = fetch.rss(tostring(url)) + + if feed_info_keys then + local feed_info_keys = string_to_ipairs(tostring(feed_info_keys)) + local feed = data.feed + local feed_info_filtered = filter_table(feed, feed_info_keys) + + tex.sprint(table_to_text(feed_info_filtered)) + end + + local entries = {} + + for i = 1, limit do + if data.entries[i] then + table.insert(entries, data.entries[i]) + end + end + + if entry_keys then + local entry_keys = string_to_ipairs(tostring(entry_keys)) + local entries_filtered = filter_table(entries, entry_keys) + + print_table(entries_filtered) + tex.sprint(table_to_text(entries_filtered)) + else + tex.sprint(table_to_text(entries)) + end +end + +--- Print the reponse from a request using query parameters to the PDF-Document. +-- @param url URL of the API +-- @param keys keys to filter out the relevant values +-- @param ... multiple optional query parameters used in the request +function M.json_using_query(url, keys, ...) + local query_parameters = { ... } + local data = fetch.json_using_query(url, query_parameters) + + print_table(data) + + local keys = string_to_ipairs(tostring(keys)) + local values = filter_table(data, keys) + tex.sprint(table_to_text(values)) +end + +return M diff --git a/macros/luatex/latex/luahttp/luahttp-doc.pdf b/macros/luatex/latex/luahttp/luahttp-doc.pdf index 99e690688a..1063d5b333 100644 Binary files a/macros/luatex/latex/luahttp/luahttp-doc.pdf and b/macros/luatex/latex/luahttp/luahttp-doc.pdf differ diff --git a/macros/luatex/latex/luahttp/luahttp-doc.tex b/macros/luatex/latex/luahttp/luahttp-doc.tex index fba575a478..210c12a26e 100644 --- a/macros/luatex/latex/luahttp/luahttp-doc.tex +++ b/macros/luatex/latex/luahttp/luahttp-doc.tex @@ -20,6 +20,7 @@ \title{The \textsf{LuaHTTP} package} \author{Johannes Casaburi \\ \texttt{johannes.casaburi@protonmail.com}} +\date{\today\\Version 1.0.1} \maketitle diff --git a/macros/luatex/latex/luahttp/luahttp-fetch.lua b/macros/luatex/latex/luahttp/luahttp-fetch.lua new file mode 100644 index 0000000000..c39997173d --- /dev/null +++ b/macros/luatex/latex/luahttp/luahttp-fetch.lua @@ -0,0 +1,199 @@ +--[[ +-- This module is part of the LuaHTTP package +-- The purpose of this module is to make HTTP requests and return the response. +-- +-- Dependencies: +-- dkjson +-- luasec +-- ltn12 +-- feedparser +]] + +local moduleName = fetch +local M = {} + +---------- Dependencies ------------------------ +local http = require("socket.http") +local urlsocket = require("socket.url") +local https = require("ssl.https") +local dkjson = require("dkjson") +local ltn12 = require("ltn12") +local feedparser = require("feedparser") + +---------- Local variables --------------------- + +---------- Helper functions -------------------- + +--- Makes an HTTP request using the provided request parameter. +-- @param request table containing the request parameters +-- @return the response as a table +local function http_request(request) + local url = request.url + print("\nConnecting to " .. url) + + -- Detect HTTPS + local client = http + if url:lower():find("^https://") then + client = https + end + + -- Save optional body + local body = request.body + + -- Prepare request + local response = {} + local request = { + method = request.method or "GET", + url = url, + headers = request.headers or nil, + redirect = request.redirect or false, + sink = ltn12.sink.table(response) + } + + -- Send optional body + if body then + if type(body) == "table" then + body = dkjson.encode(body) + end + request.source = ltn12.source.string(body) + request.headers["Content-Length"] = #body + end + + -- Make the request + local response_status, response_code, response_header, response_message = client.request(request) + + local message = response_message or "(No response message recieved)" + + if response_status == nil then + error("\n!!! Error connecting to " .. url .. "\nResponse: " .. response_code .. "\nMessage: " .. message) + end + + -- Check for redirects and return body + if response_code == 301 or response_code == 302 or response_code == 303 then + print("\nResponse " .. message) + local redirect_url = response_header["location"] + if redirect_url == url then + error("\n!!! Error connecting to " .. url .. " results in a redirection loop") + else + print("\n!! Warning: redirecting to " .. redirect_url) + request.url = redirect_url + return http_request(request) + end + elseif response_code == 200 then + print("\nResponse " .. message) + if response == null or not next(response) then + error("\n!!! Error empty response") + end + return response + else + error("\n!!! Error connecting to " .. url .. "\nResponse: " .. response_code .. "\nMessage: " .. message) + end +end + +--- Parse the given JSON-file. +-- @param file_path path to JSON-file +-- @return table containing the JSON data +local function parse_json_file(file_path) + local file = io.open(file_path, "r") + local content = file:read("*all") + file:close() + return dkjson.decode(content) +end + +--- Split a given string on the first occurence of a given character. +-- @param str string containing the given character +-- @param char target character at which the string gets split +-- @return table containing the first part of the string as the key and the second part as the value +local function split_first(str, char) + local result = {} + local pos = str:find(char) + local key = str:sub(1, pos - 1) + local value = str:sub(pos + 1) + result[key] = value + return result +end + +---------- Module functions -------------------- + +--- Make a GET request using the provided URL +-- @param url target URL +-- @return table containg the response +function M.json(url) + local request = { + method = "GET", + url = url, + headers = { + ["Accept"] = "application/json" + }, + } + local response = http_request(request) + return dkjson.decode(table.concat(response)) +end + +--- Make a request using the provided JSON-file +-- @param json_file_path path to JSON-file +-- @return table containg the response +function M.json_using_file(json_file_path) + print("\nUsing file " .. json_file_path) + local request = parse_json_file(json_file_path) + local response = http_request(request) + return dkjson.decode(table.concat(response)) +end + +--- Make a GET request using the provided URL +-- @param url target URL +-- @return table containg the response +function M.rss(url) + local request = { + method = "GET", + url = url, + headers = { + ["Accept"] = "application/rss+xml" + }, + } + local response = http_request(request) + return feedparser.parse(table.concat(response)) +end + +--- Fetch image data using the provided URL +-- @param url target URL leading to an image +-- @return image data +function M.image(url) + local request = { + method = "GET", + url = url + } + local response = http_request(request) + return table.concat(response) +end + +--- Make a POST request using the provided URL and query parameters +-- @param url target URL +-- @param query_parameters parameters sent in the URL +-- @return table containg the response +function M.json_using_query(url, query_parameters) + local url = url + for _, value in ipairs(query_parameters) do + local params = split_first(value, "=") + for k, v in pairs(params) do + v = string.gsub(v, "\n", "") + url = url .. k .. "=" .. urlsocket.escape(v) + end + end + + print("\nURL: " .. url) + + local request = { + method = "POST", + url = url, + headers = { + ["Accept"] = "application/json", + ["Content-Type"] = "application/x-www-form-urlencoded"; + }, + redirect = false + } + local response = http_request(request) + return dkjson.decode(table.concat(response)) +end + +return M diff --git a/macros/luatex/latex/luahttp/luahttp.sty b/macros/luatex/latex/luahttp/luahttp.sty index 226c234d0f..627687f3cb 100644 --- a/macros/luatex/latex/luahttp/luahttp.sty +++ b/macros/luatex/latex/luahttp/luahttp.sty @@ -16,7 +16,7 @@ % This work consists of the files luahttp.sty, display.lua and fetch.lua. \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{luahttp}[LuaHTTP Package, Version 1.0] +\ProvidesPackage{luahttp}[LuaHTTP Package, Version 1.0.1] \RequirePackage{ifluatex} \RequirePackage{url} @@ -28,7 +28,7 @@ version = 5.3 package.path = 'lua_modules/share/lua/' .. version .. '/?.lua;lua_modules/share/lua/' .. version .. '/?/init.lua;' .. package.path package.cpath = 'lua_modules/lib/lua/' .. version .. '/?.so;' .. package.cpath - display = require("display") + display = require("luahttp-display") } % \fetchJson{URL}[optional: "key1,key2,.."] -- cgit v1.2.3