AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Extensions (https://forums.alliedmods.net/forumdisplay.php?f=134)
-   -   REST in Pawn 1.3 - HTTP client for JSON REST APIs (Updated 2021/08/22) (https://forums.alliedmods.net/showthread.php?t=298024)

DJ Tsunami 05-30-2017 05:11

REST in Pawn 1.3 - HTTP client for JSON REST APIs (Updated 2021/08/22)
 
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

https://img.shields.io/github/workfl...xt/CI/main.svg https://img.shields.io/github/releas.../sm-ripext.svg https://img.shields.io/github/downlo...pext/total.svg

DJ Tsunami 05-30-2017 05:11

REST in Pawn Code Examples
 
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



good_live 05-30-2017 05:44

Re: REST in Pawn
 
Nice one :)

Deathknife 05-30-2017 06:53

Re: REST in Pawn
 
Sweet.

Quote:

Ability to set request headers and get response headers

Mitchell 05-30-2017 13:18

Re: REST in Pawn
 
Could be used with something like https://firebase.google.com/

splewis 05-30-2017 23:01

Re: REST in Pawn
 
This looks really nice. I've been using steamworks+smjansson for things, this might be able to replace both for me.

ofir753 05-31-2017 07:16

Re: REST in Pawn
 
Looks amazing, will use for sure!

axiom123 06-24-2017 06:06

Re: REST in Pawn - HTTP and JSON natives
 
How to return information from https? use post

ezio_auditore 07-22-2017 14:20

Re: REST in Pawn - HTTP and JSON methodmaps
 
Just a suggestion.

You can also add a function that generates the Authorization header... :D

jdlovins 07-27-2017 11:26

Re: REST in Pawn - HTTP and JSON methodmaps
 
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?


All times are GMT -4. The time now is 11:27.

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