Raised This Month: $404 Target: $400
 101% 

REST in Pawn - Communicate with JSON REST APIs


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 - Communicate with JSON REST APIs
Reply With Quote #1

This HTTP extension is specifically written for communicating with JSON REST APIs. It supports HTTPS and gzip, and provides methodmaps for JSON objects and arrays.


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 support for HTTP/2 multiplexing
  • Add ability to get response headers
  • Add ability to upload files?

Source Code
HTTP natives
JSON natives

__________________

Last edited by DJ Tsunami; 08-02-2017 at 03:29.
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"); 
Make sure to delete objects and arrays when you are done with them to free up their handle.


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(); 
You can also use the Set*() methods if you need to set values at a specific index in the array.


Nest JSON

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

JSONArray otherArray view_as<JSONArray>(someObject.Get("someArray")); 
Again, Get() creates a new handle, so make sure to delete it when you are done with it.


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.


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);
}

public 
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);
}

public 
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;
}

public 
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;
}

public 
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);
}

public 
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;
}

public 
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);

__________________

Last edited by DJ Tsunami; 07-18-2017 at 05:14.
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:16.


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