Raised This Month: $12 Target: $400
 3% 

REST in Pawn 1.3 - HTTP client for JSON REST APIs (Updated 2021/08/22)


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
DJ Tsunami
DJ Post Spammer
Join Date: Feb 2008
Location: The Netherlands
Old 05-30-2017 , 05:11   REST in Pawn 1.3 - HTTP client for JSON REST APIs (Updated 2021/08/22)
Reply With Quote #1

This extension exposes a high performance HTTP client for JSON REST APIs. It supports HTTP/2, HTTPS and gzip, and provides methodmaps for JSON objects and arrays.

Requires SourceMod 1.10 or later.

Note that requests are not processed during hibernation. You can set sv_hibernate_when_empty to 0 to disable hibernation.

Note that HTTP/2 is only attempted over HTTPS, in line with most web clients.


Installation
  1. Click Download.
  2. Download and extract the file for your server's operating system.
  3. Upload the files in the addons/sourcemod directory to your server.

Source Code
HTTP natives
JSON natives

__________________
Advertisements | REST in Pawn - HTTP client for JSON REST APIs
Please do not PM me with questions. Post in the plugin thread.

Last edited by DJ Tsunami; 10-08-2021 at 16:24.
DJ Tsunami is offline
DJ Tsunami
DJ Post Spammer
Join Date: Feb 2008
Location: The Netherlands
Old 05-30-2017 , 05:11   REST in Pawn Code Examples
Reply With Quote #2

Code Examples

JSON

Create a JSON object

PHP Code:
JSONObject someObject = new JSONObject();

someObject.SetBool("someBool"false);
someObject.SetFloat("someFloat"1.0);
someObject.SetInt("someInt"2);
someObject.SetString("someString""three");
someObject.SetNull("someNull");

delete someObject

Create a JSON array

PHP Code:
JSONArray someArray = new JSONArray();

someArray.PushBool(false);
someArray.PushFloat(1.0);
someArray.PushInt(2);
someArray.PushString("three");
someArray.PushNull();

delete someArray
You can use the Set*() methods if you need to replace values at a specific index in the array.


Nest JSON

PHP Code:
someObject.Set("someArray"someArray);

JSONArray someArrayCopy view_as<JSONArray>(someObject.Get("someArray"));

delete someArrayCopy

Export to and import from files and strings

PHP Code:
char json[1024];
someObject.ToString(jsonsizeof(json));


char path[PLATFORM_MAX_PATH];
BuildPath(Path_SMpathsizeof(path), "data/array.json");

JSONArray someArray JSONArray.FromFile(path); 
See the encoding flags at the top of json.inc if you want to format the output.


Iterate over the keys in a JSON object

PHP Code:
JSONObjectKeys keys someObject.Keys();
char key[64];

while (
keys.ReadKey(keysizeof(key))) {
    
PrintToServer("%s"key);
}

delete keys

HTTP

Retrieve an item

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos/1");

    
request.Get(OnTodoReceived);
}

void OnTodoReceived(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_OK) {
        
// Failed to retrieve todo
        
return;
    }

    
// Indicate that the response contains a JSON object
    
JSONObject todo view_as<JSONObject>(response.Data);

    
char title[256];
    
todo.GetString("title"titlesizeof(title));

    
PrintToServer("Retrieved todo with title '%s'"title);


Retrieve a collection

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos");

    
request.Get(OnTodosReceived);
}

void OnTodosReceived(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_OK) {
        
// Failed to retrieve todos
        
return;
    }

    
// Indicate that the response contains a JSON array
    
JSONArray todos view_as<JSONArray>(response.Data);
    
int numTodos todos.Length;

    
JSONObject todo;
    
char title[256];

    for (
int i 0numTodosi++) {
        
todo view_as<JSONObject>(todos.Get(i));

        
todo.GetString("title"titlesizeof(title));

        
PrintToServer("Retrieved todo with title '%s'"title);

        
// Get() creates a new handle, so delete it when you are done with it
        
delete todo;
    }


Create an item

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
JSONObject todo = new JSONObject();
    
todo.SetBool("completed"false);
    
todo.SetInt("userId"1);
    
todo.SetString("title""foo");

    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos");
    
request.Post(todoOnTodoCreated);

    
// JSON objects and arrays must be deleted when you are done with them
    
delete todo;
}

void OnTodoCreated(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_Created) {
        
// Failed to create todo
        
return;
    }

    
JSONObject todo view_as<JSONObject>(response.Data);

    
PrintToServer("Created todo with ID %d"todo.GetInt("id"));


Update an item

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
JSONObject todo = new JSONObject();
    
todo.SetBool("completed"true);

    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos/1");
    
// Some APIs replace the entire object when using Put,
    // in which case you need to use Patch instead.
    
httpClient.Put(todoOnTodoUpdated);

    
delete todo;
}

void OnTodoUpdated(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_OK) {
        
// Failed to update todo
        
return;
    }

    
JSONObject todo view_as<JSONObject>(response.Data);

    
PrintToServer("Updated todo with ID %d"todo.GetInt("id"));


Delete an item

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos/1");

    
request.Delete(OnTodoDeleted);
}

void OnTodoDeleted(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_OK) {
        
// Failed to delete todo
        
return;
    }

    
PrintToServer("Deleted todo");

Append query parameters to the URL

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos");

    
request.AppendQueryParam("userId""%d"1);

The parameter name and value are automatically URL encoded.


Set the credentials for HTTP Basic authentication

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://nghttp2.org/httpbin/basic-auth/username/password");

    
request.SetBasicAuth("username""password");

Set request headers

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://nghttp2.org/httpbin/bearer");

    
request.SetHeader("Authorization""Bearer %s""some-token");

Get response headers

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://nghttp2.org/httpbin/get");

    
request.Get(OnTodosReceived);
}

void OnTodosReceived(HTTPResponse responseany value)
{
    
char date[30];
    
response.GetHeader("Date"datesizeof(date));

    
PrintToServer("Date: %s"date);


Resource methodmaps

You can also write your own methodmaps which inherit from JSONObject, and which abstract away the fields of a resource. This makes your code cleaner when reading and writing resources.


plugin.inc

PHP Code:
methodmap Todo JSONObject
{
    
// Constructor
    
public Todo() { return view_as<Todo>(new JSONObject()); }

    public 
void GetTitle(char[] bufferint maxlength)
    {
        
this.GetString("title"buffermaxlength);
    }
    public 
void SetTitle(const char[] value)
    {
        
this.SetString("title"value);
    }

    
property bool Completed {
        public 
get() { return this.GetBool("completed"); }
        public 
set(bool value) { this.SetBool("completed"value); }
    }
    
property int Id {
        public 
get() { return this.GetInt("id"); }
    }
    
property int UserId {
        public 
get() { return this.GetInt("userId"); }
        public 
set(int value) { this.SetInt("userId"value); }
    }
}; 

plugin.sp

PHP Code:
#include <sourcemod>
#include <ripext>
#include <plugin>

public void OnPluginStart()
{
    
Todo todo = new Todo();
    
todo.Completed false;
    
todo.UserId 1;
    
todo.SetTitle("foo");

    
HTTPRequest request = new HTTPRequest("https://jsonplaceholder.typicode.com/todos");
    
request.Post(todoOnTodoCreated);

    
delete todo;
}

void OnTodoCreated(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_Created) {
        
// Failed to create todo
        
return;
    }

    
Todo todo view_as<Todo>(response.Data);

    
PrintToServer("Todo created with ID %d"todo.Id);


Files

Download a file

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
char imagePath[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMimagePathsizeof(imagePath), "data/image.jpg");

    
HTTPRequest request = new HTTPRequest("https://nghttp2.org/httpbin/image/jpeg");
    
request.DownloadFile(imagePathOnImageDownloaded);
}

void OnImageDownloaded(HTTPStatus statusany value)
{
    if (
status != HTTPStatus_OK) {
        
// Download failed
        
return;
    }

    
PrintToServer("Download complete");


Upload a file

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
char imagePath[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMimagePathsizeof(imagePath), "data/image.jpg");

    
HTTPRequest request = new HTTPRequest("https://example.com/upload");
    
request.UploadFile(imagePathOnImageUploaded);
}

void OnImageUploaded(HTTPStatus statusany value)
{
    if (
status != HTTPStatus_OK) {
        
// Upload failed
        
return;
    }

    
PrintToServer("Upload complete");


Forms

Post form data

PHP Code:
#include <sourcemod>
#include <ripext>

public void OnPluginStart()
{
    
HTTPRequest request = new HTTPRequest("https://nghttp2.org/httpbin/post");

    
request.AppendFormParam("title""%s""foo");
    
request.PostForm(OnFormPosted);
}

void OnFormPosted(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_OK) {
        
// Failed to post form
        
return;
    }

    
// The JSON response data can be retrieved here

__________________
Advertisements | REST in Pawn - HTTP client for JSON REST APIs
Please do not PM me with questions. Post in the plugin thread.

Last edited by DJ Tsunami; 06-05-2021 at 13:52.
DJ Tsunami is offline
good_live
AlliedModders Donor
Join Date: Oct 2013
Old 05-30-2017 , 05:44   Re: REST in Pawn
Reply With Quote #3

Nice one
good_live is offline
Deathknife
Senior Member
Join Date: Aug 2014
Old 05-30-2017 , 06:53   Re: REST in Pawn
Reply With Quote #4

Sweet.

Quote:
Ability to set request headers and get response headers
__________________
Deathknife is offline
Mitchell
~lick~
Join Date: Mar 2010
Old 05-30-2017 , 13:18   Re: REST in Pawn
Reply With Quote #5

Could be used with something like https://firebase.google.com/
Mitchell is offline
splewis
Veteran Member
Join Date: Feb 2014
Location: United States
Old 05-30-2017 , 23:01   Re: REST in Pawn
Reply With Quote #6

This looks really nice. I've been using steamworks+smjansson for things, this might be able to replace both for me.
__________________
splewis is offline
ofir753
Senior Member
Join Date: Aug 2012
Old 05-31-2017 , 07:16   Re: REST in Pawn
Reply With Quote #7

Looks amazing, will use for sure!
ofir753 is offline
axiom123
Member
Join Date: May 2013
Location: Ukraine, Kiev
Old 06-24-2017 , 06:06   Re: REST in Pawn - HTTP and JSON natives
Reply With Quote #8

How to return information from https? use post

Last edited by axiom123; 06-24-2017 at 07:00.
axiom123 is offline
Send a message via ICQ to axiom123 Send a message via Skype™ to axiom123
ezio_auditore
Senior Member
Join Date: May 2013
Old 07-22-2017 , 14:20   Re: REST in Pawn - HTTP and JSON methodmaps
Reply With Quote #9

Just a suggestion.

You can also add a function that generates the Authorization header...
__________________
ezio_auditore is offline
Send a message via Skype™ to ezio_auditore
jdlovins
Junior Member
Join Date: Sep 2015
Old 07-27-2017 , 11:26   Re: REST in Pawn - HTTP and JSON methodmaps
Reply With Quote #10

Quick question,

Do i have to delete response.Data after im done with the data or does that get auto cleaned up? In your examples you only delete the handles spawned by looping through an array.

Thanks!

edit:

looking at the source,

Code:
handlesys->FreeHandle(hndlResponse, &sec);
handlesys->FreeHandle(response.hndlData, &sec);
I guess this takes care of the JSON response and the actual response handles?

Last edited by jdlovins; 07-27-2017 at 11:29.
jdlovins is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 09:58.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode