GithubHelp home page GithubHelp logo

williamvenner / gmsv_reqwest Goto Github PK

View Code? Open in Web Editor NEW
59.0 4.0 3.0 75 KB

๐ŸŒ Drop-in HTTP replacement module for Garry's Mod

License: MIT License

Rust 100.00%
gmod garrysmod garrys-mod gmsv gmod-modules gmod-module discord http rust glua

gmsv_reqwest's Introduction

๐ŸŒ gmsv_reqwest

This module is a drop-in replacement for Garry's Mod's HTTP function, inspired by gmsv_chttp created by timschumi.

The module uses the reqwest crate for dispatching HTTP requests, tokio crate for async/thread scheduling runtime and the rustls crate for SSL/TLS.

This module was written in Rust and serves as a decent example on how to write a Garry's Mod binary module in Rust, using the gmod crate.

Installation

Download the relevant module for your server's operating system and platform/Gmod branch from the releases section.

Drop the module into garrysmod/lua/bin/ in your server's files. If the bin folder doesn't exist, create it.

If you're not sure on what operating system/platform your server is running, run this in your server's console:

lua_run print((system.IsWindows()and"Windows"or system.IsLinux()and"Linux"or"Unsupported").." "..(jit.arch=="x64"and"x86-64"or"x86"))

Custom root certificates (for SSL/TLS)

To add custom root certificates, place them in the garrysmod/tls_certificates/client directory.

The certificates must be X509 and encoded in either pem or der. They must also end in the .pem or .der file extensions respective to their econding. If there is a problem loading the certificate, it'll be skipped over and a message will be displayed in the console.

Overriding Garry's Mod HTTP

To override Garry's Mod's HTTP function with reqwest, you can add this code snippet to lua/autorun/server/reqwest.lua:

if pcall(require, "reqwest") and reqwest ~= nil then
    my_http = reqwest
else
    my_http = HTTP
end

Developer Usage

Once loaded, gmsv_reqwest will create a global function called reqwest which behaves exactly the same as HTTP and uses the same configuration struct (HTTPRequest).

There is one difference: on HTTP request failure, reqwest will provide an extended error message (known as errExt) as well as Garry's Mod's useless error message.

Discord Webhook Example

require("reqwest")

reqwest({
    method = "POST",
    url = "https://discord.com/api/webhooks/988854737435070417/pHbHIjR15oa4ZmJ1PMCwEPaK4hdlCC21AIme94Iw9Xh7M9Mhg6GLLV2u6Q1rppH_7esX",
    timeout = 30,
    
    body = util.TableToJSON({ content = "Hello, world!" }), -- https://discord.com/developers/docs/resources/webhook#execute-webhook
    type = "application/json",

    headers = {
        ["User-Agent"] = "My User Agent", -- This is REQUIRED to dispatch a Discord webhook
    },

    success = function(status, body, headers)
        print("HTTP " .. status)
        PrintTable(headers)
        print(body)
    end,

    failed = function(err, errExt)
        print("Error: " .. err .. " (" .. errExt .. ")")
    end
})

By the way, that webhook URL is fake :D

Support both gmsv_reqwest and gmsv_chttp

This example loads either reqwest or CHTTP

if not reqwest and not CHTTP then
    local suffix = ({"osx64", "osx", "linux64", "linux", "win64", "win32"})[(system.IsWindows() and 4 or 0) + (system.IsLinux() and 2 or 0) + (jit.arch == "x86" and 1 or 0) + 1]
    local fmt = "lua/bin/gm" .. (CLIENT and "cl" or "sv") .. "_%s_%s.dll"
    local function installed(name)
        if file.Exists(string.format(fmt, name, suffix), "GAME") then return true end
        if jit.versionnum ~= 20004 and jit.arch == "x86" and system.IsLinux() then return file.Exists(string.format(fmt, name, "linux32"), "GAME") end
        return false
    end

    if installed("reqwest") then
        require("reqwest")
    end
    if not reqwest and installed("chttp") then
        require("chttp")
    end
    if not CHTTP then
        error("reqwest or CHTTP is required to use this!")
    end
end

local HTTP = reqwest or CHTTP

-- Your code

Thread-blocking requests

You can make requests that block the main thread using gmsv_reqwest, i.e., they are not asynchronous.

  • Only do this if you know what you are doing.
  • Make sure that you choose an appropriate timeout to avoid timing out players if any are online and the request hangs.
  • If you provide a success and failed callback, they will still be called
  • On success, true, status, body and headers will be returned
  • On failure, false, err, errExt will be returned

To do this, simply add blocking = true to the HTTPRequest table when creating your HTTP request.

Example

require("reqwest")

local success, status, body, headers = reqwest({
    blocking = true, -- note this!

    url = "https://google.com",

    -- callbacks will still be called for blocking requests
    success = function(status, body, headers) PrintTable({status, body, headers}) end,
    failed = function(err, errExt) PrintTable({err, errExt}) end
})
if success then
    print("HTTP " .. status)
    PrintTable(headers)
    print(body)
else
    local err, errExt = status, body
    -- In this case, `status` will be the "error message" that Garry's Mod provides (typically always "unsuccessful")
    --  and `body` will be a custom error message from reqwest which actually describes what the error was.
    print("Error: " .. err .. " (" .. errExt .. ")")
end

gmsv_reqwest's People

Contributors

nosharp avatar williamvenner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

gmsv_reqwest's Issues

TraceLine error when onfailed function is passed and request is success

Details

Protocol version 24
Exe version 2021.06.09 (garrysmod)
Exe build: 14:40:17 Jul 12 2021 (8283) (4000)
GMod version 2021.07.12, branch: unknown, multicore: 0
Windows 32bit

Step to reproduce

Sandbox gamemode
No addons enabled
No other modules included
main branch (tested with 1.1.1, 1.1.0, 1.0.0 module versions)

if not reqwest then
	require"reqwest"
end

local function onfailed(r)
	print("Failed:", r)
end

local function onsuccess(code, body, headers)
	print("Success:", code, headers)
end

reqwest({
	failed = onfailed,
	success = onsuccess,
	method = "GET",
	url = "https://github.com/WilliamVenner/gmsv_reqwest"
})

Result:

Success:	200	table: 0x466aac48

[ERROR] attempt to index a function value
  1. TraceLine - [C]:-1
   2. UpdateHovered - lua/includes/modules/widget.lua:46
    3. PlayerTick - lua/includes/modules/widget.lua:89
     4. v - lua/includes/modules/widget.lua:149
      5. unknown - lua/includes/modules/hook.lua:84

No error when failed func not passed

if not reqwest then
	require"reqwest"
end

local function onsuccess(code, body, headers)
	print("Success:", code, headers)
end

reqwest({
	success = onsuccess,
	method = "GET",
	url = "https://github.com/WilliamVenner/gmsv_reqwest"
})

Result:

Success:	200	table: 0x177709d8

Also no error when request is failed

if not reqwest then
	require"reqwest"
end

local function onfailed(r)
	print("Failed:", r)
end

local function onsuccess(code, body, headers)
	print("Success:", code, headers)
end

reqwest({
	failed = onfailed,
	success = onsuccess,
	method = "GET",
	url = "https://this_willbe_failed/"
})

Result:

Failed:	unsuccessful

Big suspend when invalid url provided

] version
Protocol version 24
Exe version 2022.06.08 (garrysmod)
Exe build: 18:31:37 Jun  1 2022 (8607) (4000)
GMod version 2022.06.10, branch: unknown, multicore: 1
Windows 32bit

Sometimes suspend lasts more than 2 minutes, which is enough for another module to turn off the server, considering it a hang, "resume" in process hacker helps to solve it faster

hl2_RIyEUB4TsT.mp4

Linux x32 build won't require due to missing GLIBC version

I'm using Ubuntu 16.04, this issue seems to be when it's compiled with a version of GLIBC that is too high for people running certain Ubuntu versions.

[ERROR] error loading module 'reqwest' from file 'gmsv_reqwest_linux.dll':
        /lib/i386-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /home/container/garrysmod/lua/bin/gmsv_reqwest_linux.dll)
  1. error - [C]:-1
   2. searcher - lua/test.lua:65
    3. require - lua/test.lua:148
     4. unknown - lua_run:1

Similar issue: FredyH/GWSockets#10

Game crash on require("reqwest")

My game crashes instantly whenever i do require("reqwest") on serverside, tried in p2p and singleplayer, no crash logs are generated. Any idea what could cause this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.