Raised This Month: $60 Target: $400
 15% 

REST in Pawn 1.2 - HTTP client for JSON REST APIs (Updated 2020/06/21)


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
DJ Tsunami
DJ Post Spammer
Join Date: Feb 2008
Old 05-30-2017 , 05:11   REST in Pawn 1.2 - HTTP client for JSON REST APIs (Updated 2020/06/21)
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.


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.

To Do
  • Add ability to encode URLs

Source Code
HTTP natives
JSON natives

__________________

Last edited by DJ Tsunami; 06-21-2020 at 14:00.
DJ Tsunami is offline
DJ Tsunami
DJ Post Spammer
Join Date: Feb 2008
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 arrayCopy view_as<JSONArray>(someObject.Get("someArray"));

delete arrayCopy

Export to and import from files and strings

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


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

JSONArray fileArray 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

Set request headers

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

    
httpClient.SetHeader("Authorization""Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");

Retrieve an item

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

    
httpClient.Get("todos/1"OnTodoReceived);
}

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

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

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

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


Retrieve a collection

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

    
httpClient.Get("todos"OnTodosReceived);
}

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

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

    
JSONObject todo;
    
char todoTitle[256];

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

        
todo.GetString("title"todoTitlesizeof(todoTitle));

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

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


Create an item

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

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

    
httpClient.Post("todos"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;
    }
    if (
response.Data == null) {
        
// Invalid JSON response
        
return;
    }

    
JSONObject todo view_as<JSONObject>(response.Data);
    
int todoId todo.GetInt("id");

    
PrintToServer("Created todo with ID %d"todoId);


Update an item

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

    
JSONObject todo = new JSONObject();
    
todo.SetBool("completed"true);

    
// Some APIs replace the entire object when using PUT,
    // in which case you need to use PATCH instead.
    
httpClient.Put("todos/1"todoOnTodoUpdated);

    
delete todo;
}

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

    
JSONObject todo view_as<JSONObject>(response.Data);
    
int todoId todo.GetInt("id");

    
PrintToServer("Updated todo with ID %d"todoId);


Delete an item

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

    
httpClient.Delete("todos/1"OnTodoDeleted1);
}

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

    
PrintToServer("Deleted todo with ID %d"value);


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>

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://jsonplaceholder.typicode.com");

    
Todo todo = new Todo();
    
todo.Completed false;
    
todo.UserId 1;
    
todo.SetTitle("foo");

    
httpClient.Post("todos"todoOnTodoCreated);

    
delete todo;
}

void OnTodoCreated(HTTPResponse responseany value)
{
    if (
response.Status != HTTPStatus_Created) {
        
// Failed to create todo
        
return;
    }
    if (
response.Data == null) {
        
// Invalid JSON response
        
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>

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://nghttp2.org/httpbin");

    
char sImagePath[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMsImagePathsizeof(sImagePath), "data/image.jpg");

    
httpClient.DownloadFile("image/jpeg"sImagePathOnImageDownloaded);
}

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

    
PrintToServer("Download complete");


Upload a file

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

HTTPClient httpClient;

public 
void OnPluginStart()
{
    
httpClient = new HTTPClient("https://example.com");

    
char sImagePath[PLATFORM_MAX_PATH];
    
BuildPath(Path_SMsImagePathsizeof(sImagePath), "data/image.jpg");

    
httpClient.UploadFile("upload"sImagePathOnImageUploaded);
}

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

    
PrintToServer("Upload complete");

__________________

Last edited by DJ Tsunami; 07-10-2020 at 12:05.
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 04:25.


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