Skip to content

Commit 6c2f910

Browse files
committed
feat(http): improved http related functions
- Add PostJson, PostForm, PutJson, PatchJson methods - Add form parameter handling with AppendFormParam - Remove generic GET methods - Add URL encoding support for form parameters - Update method signatures in header files - Update native bindings - Add comprehensive test script for HTTP client - Include examples for all HTTP methods - Add form data and JSON payload examples - Add response handling examples - Add header manipulation examples - Use httpbin.org as test endpoint This change improves the HTTP client API by providing more specific and type-safe methods for different request body types
1 parent 4f24604 commit 6c2f910

13 files changed

Lines changed: 785 additions & 128 deletions

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This is a [SourceMod](http://www.sourcemod.net/) extension that provides some me
1111
* Support permessage-deflate
1212
* Support SSL
1313
* Support x64
14+
* Support HTTP RESTful API with JSON and form data
1415

1516
## How to build this?
1617
``` sh
@@ -26,17 +27,17 @@ ambuild
2627
## Native
2728
* [json](https://github.com/ProjectSky/sm-ext-websocket/blob/main/scripting/include/websocket/yyjson.inc)
2829
* [websocket](https://github.com/ProjectSky/sm-ext-websocket/blob/main/scripting/include/websocket/ws.inc)
30+
* [http](https://github.com/ProjectSky/sm-ext-websocket/blob/main/scripting/include/websocket/http.inc)
2931

3032
# Binary files
3133
* [GitHub Releases](https://github.com/ProjectSky/sm-ext-websocket/releases)
3234

3335
## TODO
3436
- [x] WebSocket server support
3537
- [x] Windows support
36-
- [ ] HTTP support? (Because this is a WebSocket library I might not support it)
38+
- [x] HTTP support
3739

3840
## NOTES
39-
* HTTP functionality is not yet complete. Currently, only basic features are available
4041
* Server will not process data during the hibernation. You can set sv_hibernate_when_empty to 0 to disable hibernation
4142

4243
## Example

pushbuild.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
0x1
33
0x2
44
0x3
5-
0x4
5+
0x4
6+
0x5

scripting/http_test.sp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#include <sourcemod>
2+
#include <websocket>
3+
4+
public Plugin myinfo = {
5+
name = "HTTP Client Test",
6+
author = "ProjectSky",
7+
description = "Used for testing HTTP client",
8+
version = "1.0.0",
9+
url = "https://github.com/ProjectSky/sm-ext-websocket"
10+
}
11+
12+
public void OnPluginStart()
13+
{
14+
RegServerCmd("http_get", http_get);
15+
RegServerCmd("http_post_json", http_post_json);
16+
RegServerCmd("http_post_form", http_post_form);
17+
RegServerCmd("http_put", http_put);
18+
RegServerCmd("http_patch", http_patch);
19+
RegServerCmd("http_delete", http_delete);
20+
}
21+
22+
Action http_get(int args)
23+
{
24+
HttpRequest request = new HttpRequest("https://httpbin.org/get");
25+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
26+
request.Get(OnHttpResponse);
27+
return Plugin_Handled;
28+
}
29+
30+
Action http_post_json(int args)
31+
{
32+
HttpRequest request = new HttpRequest("https://httpbin.org/post");
33+
34+
// Create JSON payload
35+
YYJSONObject json = new YYJSONObject();
36+
json.SetString("name", "test");
37+
json.SetInt("age", 25);
38+
json.SetBool("active", true);
39+
40+
// Add custom headers
41+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
42+
43+
// Send POST request with JSON body
44+
request.PostJson(json, OnHttpResponse);
45+
46+
delete json;
47+
return Plugin_Handled;
48+
}
49+
50+
Action http_post_form(int args)
51+
{
52+
HttpRequest request = new HttpRequest("https://httpbin.org/post");
53+
54+
// Add form parameters
55+
request.AppendFormParam("username", "john_doe");
56+
request.AppendFormParam("email", "john@example.com");
57+
request.AppendFormParam("age", "25");
58+
59+
// Add custom headers
60+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
61+
62+
// Send POST request with form data
63+
request.PostForm(OnHttpResponse);
64+
return Plugin_Handled;
65+
}
66+
67+
Action http_put(int args)
68+
{
69+
HttpRequest request = new HttpRequest("https://httpbin.org/put");
70+
71+
// Create JSON payload for PUT
72+
YYJSONObject json = new YYJSONObject();
73+
json.SetString("id", "123");
74+
json.SetString("name", "updated_name");
75+
json.SetBool("active", false);
76+
77+
// Add custom headers
78+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
79+
80+
// Send PUT request with JSON body
81+
request.PutJson(json, OnHttpResponse);
82+
83+
delete json;
84+
return Plugin_Handled;
85+
}
86+
87+
Action http_patch(int args)
88+
{
89+
HttpRequest request = new HttpRequest("https://httpbin.org/patch");
90+
91+
// Create JSON payload for PATCH
92+
YYJSONObject json = new YYJSONObject();
93+
json.SetString("name", "partial_update");
94+
95+
// Add custom headers
96+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
97+
98+
// Send PATCH request with JSON body
99+
request.PatchJson(json, OnHttpResponse);
100+
101+
delete json;
102+
return Plugin_Handled;
103+
}
104+
105+
Action http_delete(int args)
106+
{
107+
HttpRequest request = new HttpRequest("https://httpbin.org/delete");
108+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
109+
request.Delete(OnHttpResponse);
110+
return Plugin_Handled;
111+
}
112+
113+
void OnHttpResponse(HttpRequest http, const char[] body, int statusCode, int bodySize, any value)
114+
{
115+
// Print response details
116+
PrintToServer("Status Code: %d", statusCode);
117+
PrintToServer("Body Size: %d bytes", bodySize);
118+
119+
// Print response headers
120+
char headerValue[256];
121+
if (http.GetResponseHeader("Content-Type", headerValue, sizeof(headerValue)))
122+
{
123+
PrintToServer("Content-Type: %s", headerValue);
124+
}
125+
126+
// Print response body
127+
PrintToServer("Response Body: %s", body);
128+
}

scripting/include/websocket/http.inc

Lines changed: 107 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,67 +6,145 @@ typeset ResponseCallback
66
/**
77
* Function called when an HTTP response is received
88
*
9-
* @param http HTTP request object
10-
* @param body Response body
11-
* @param statusCode HTTP status code
12-
* @param bodySize Size of the response body
9+
* @param http HTTP request object
10+
* @param body Response body
11+
* @param statusCode HTTP status code
12+
* @param bodySize Size of the response body
13+
* @param value Value passed to the HTTP method
1314
*/
14-
function void (HttpRequest http, const char[] body, int statusCode, int bodySize);
15+
function void (HttpRequest http, const char[] body, int statusCode, int bodySize, any value);
1516
}
1617

17-
// Define a methodmap for HttpRequest, which extends Handle
1818
methodmap HttpRequest < Handle
1919
{
2020
/**
2121
* Create a new HTTP request
2222
*
23-
* @param url Request URL
24-
* @param method HTTP method (default is "GET")
23+
* @param url Request URL
2524
*/
26-
public native HttpRequest(const char[] url, const char[] method = "GET");
25+
public native HttpRequest(const char[] url);
2726

2827
/**
29-
* Set the callback for when an HTTP response is received
28+
* Performs a GET request
29+
* GET requests should not have a body, only query parameters in URL
3030
*
31-
* @param fResponse Function to call when an HTTP response is received
31+
* @param fResponse Function to call when an HTTP response is received
32+
* @param value Value to pass to the callback
33+
* @return True if the request was sent successfully, false otherwise
3234
*/
33-
public native void SetResponseCallback(ResponseCallback fResponse);
35+
public native bool Get(ResponseCallback fResponse, any value = 0);
3436

3537
/**
36-
* Perform the HTTP request
38+
* Performs a POST request with JSON body
39+
* POST requests typically send data to create a new resource
40+
*
41+
* @param json JSON data to send in request body
42+
* @param fResponse Function to call when an HTTP response is received
43+
* @param value Value to pass to the callback
44+
* @return True if the request was sent successfully, false otherwise
45+
*/
46+
public native bool PostJson(const YYJSON json, ResponseCallback fResponse, any value = 0);
47+
48+
/**
49+
* Performs a POST request with accumulated form parameters
50+
* Uses application/x-www-form-urlencoded format
51+
*
52+
* @param fResponse Function to call when an HTTP response is received
53+
* @param value Value to pass to the callback
54+
* @return True if the request was sent successfully, false otherwise
55+
*/
56+
public native bool PostForm(ResponseCallback fResponse, any value = 0);
57+
58+
/**
59+
* Performs a PUT request with JSON body
60+
* PUT requests typically update an entire resource
61+
*
62+
* @param json JSON data to send in request body
63+
* @param fResponse Function to call when an HTTP response is received
64+
* @param value Value to pass to the callback
65+
* @return True if the request was sent successfully, false otherwise
66+
*/
67+
public native bool PutJson(const YYJSON json, ResponseCallback fResponse, any value = 0);
68+
69+
/**
70+
* Performs a PATCH request with JSON body
71+
* PATCH requests typically perform partial updates to a resource
72+
*
73+
* @param json JSON data containing the fields to update
74+
* @param fResponse Function to call when an HTTP response is received
75+
* @param value Value to pass to the callback
76+
* @return True if the request was sent successfully, false otherwise
77+
*/
78+
public native bool PatchJson(const YYJSON json, ResponseCallback fResponse, any value = 0);
79+
80+
/**
81+
* Performs a DELETE request
82+
* DELETE requests typically don't have a body
83+
*
84+
* @param fResponse Function to call when an HTTP response is received
85+
* @param value Value to pass to the callback
86+
* @return True if the request was sent successfully, false otherwise
3787
*/
38-
public native void Perform();
88+
public native bool Delete(ResponseCallback fResponse, any value = 0);
3989

4090
/**
41-
* Set the body of the HTTP request
91+
* Append a form parameter to the request
92+
* Multiple calls will accumulate parameters for the next form submission
4293
*
43-
* @param body Body of the request
94+
* @param key Parameter key
95+
* @param value Parameter value
96+
* @return True if parameter was added successfully
4497
*/
45-
public native void SetBody(const char[] body);
98+
public native bool AppendFormParam(const char[] key, const char[] value);
4699

47100
/**
48101
* Add a header to the HTTP request
49102
*
50-
* @param key Header key
51-
* @param value Header value
103+
* @param key Header key
104+
* @param value Header value
52105
*/
53106
public native void AddHeader(const char[] key, const char[] value);
54107

55108
/**
56-
* Get a header from the HTTP request
109+
* Get a response header from the HTTP request
57110
*
58-
* @param key Header key
59-
* @param value Buffer to store the header value
60-
* @param maxLength Maximum length of the value buffer
61-
* @return True if the header was found, false otherwise
111+
* @param key Header key
112+
* @param value Buffer to store the header value
113+
* @param maxLength Maximum length of the value buffer
114+
* @return True if the header was found, false otherwise
62115
*/
63-
public native bool GetHeader(const char[] key, char[] value, int maxLength);
116+
public native bool GetResponseHeader(const char[] key, char[] value, int maxLength);
64117

65118
/**
66-
* Check if a header exists in the HTTP request
119+
* Check if a response header exists in the HTTP request
67120
*
68-
* @param key Header key
69-
* @return True if the header exists, false otherwise
121+
* @param key Header key
122+
* @return True if the header exists, false otherwise
70123
*/
71-
public native bool HasHeader(const char[] key);
124+
public native bool HasResponseHeader(const char[] key);
125+
126+
property int Timeout {
127+
public native get();
128+
public native set(int timeout);
129+
}
130+
131+
property bool FollowRedirect {
132+
public native get();
133+
public native set(bool follow);
134+
}
135+
136+
property bool Compression {
137+
public native get();
138+
public native set(bool compress);
139+
}
140+
141+
property int MaxRedirects {
142+
public native get();
143+
public native set(int maxRedirects);
144+
}
145+
146+
property bool Verbose {
147+
public native get();
148+
public native set(bool verbose);
149+
}
72150
}

0 commit comments

Comments
 (0)