├── Doxyfile ├── LICENSE ├── README.md ├── Source └── RestRequest.h ├── juce_module_info ├── rest_request.cpp ├── rest_request.h └── rest_request.mm /Doxyfile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = restrequest 2 | INPUT = .git .git/hooks .git/info .git/logs .git/logs/refs .git/logs/refs/heads .git/logs/refs/remotes .git/logs/refs/remotes/origin .git/objects .git/objects/19 .git/objects/27 .git/objects/2d .git/objects/30 .git/objects/31 .git/objects/33 .git/objects/3c .git/objects/ad .git/objects/ba .git/objects/be .git/objects/c9 .git/objects/info .git/objects/pack .git/refs .git/refs/heads .git/refs/remotes .git/refs/remotes/origin .git/refs/tags Source 3 | OUTPUT_DIRECTORY = docs 4 | GENERATE_LATEX = NO 5 | GENERATE_HTML = YES 6 | HTML_OUTPUT = . 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Adam Wilson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RestRequest 2 | JUCE module for making HTTP requests to REST API's 3 | 4 | ### Example Usage 5 | 6 | First declare your class instance e.g. as a member variable: 7 | ```cpp 8 | adamski::RestRequest request; 9 | ``` 10 | 11 | Then in your constructor add any headers you will need across different requests e.g.: 12 | ```cpp 13 | request.header ("Content-Type", "application/json"); 14 | request.header ("Authorization", "Basic " + Base64::toBase64 ("username:password")); 15 | ``` 16 | 17 | Example `GET` request: 18 | 19 | ```cpp 20 | adamski::RestRequest::Response response = request.get ("registry/_design/module-views/_view/all-modules") 21 | .execute(); 22 | 23 | // Example response debugging 24 | 25 | DBG (response.bodyAsString); 26 | DBG (response.result.getErrorMessage()); 27 | 28 | for (auto key : response.headers.getAllKeys()) 29 | { 30 | DBG (key << ": " << response.headers.getValue(key, "n/a")); 31 | } 32 | ``` 33 | 34 | Example `POST` request: 35 | 36 | ```cpp 37 | adamski::RestRequest::Response response = request.post ("registry/_find") 38 | .field ("selector", searchString) 39 | .execute(); 40 | ``` 41 | 42 | Example `PUT` request with chained field methods: 43 | 44 | ```cpp 45 | adamski::RestRequest::Response response = request.put ("_users/" + id) 46 | .field ("type", "user") 47 | .field ("name", username) 48 | .field ("email", email) 49 | .field ("roles", Array({var("publisher")})) 50 | .field ("password_sha", stringToSHA1 (password + salt)) 51 | .field ("salt", salt) 52 | .execute(); 53 | 54 | ``` 55 | 56 | If you need to encode or decode strings with SHA1 I made a JUCE module out of an open source library called smallsha1: https://github.com/adamski/smallsha1 57 | -------------------------------------------------------------------------------- /Source/RestRequest.h: -------------------------------------------------------------------------------- 1 | /* 2 | ============================================================================== 3 | 4 | RestRequest.h 5 | Created: 16 Dec 2015 2:29:23pm 6 | Author: Adam Wilson 7 | 8 | ============================================================================== 9 | */ 10 | 11 | #ifndef RESTREQUEST_H_INCLUDED 12 | #define RESTREQUEST_H_INCLUDED 13 | 14 | class RestRequest 15 | { 16 | public: 17 | 18 | RestRequest (String urlString) : url (urlString) {} 19 | RestRequest (URL url) : url (url) {} 20 | RestRequest () {} 21 | 22 | struct Response 23 | { 24 | Result result; 25 | StringPairArray headers; 26 | var body; 27 | String bodyAsString; 28 | int status; 29 | 30 | Response() : result (Result::ok()), status (0) {} // not sure about using Result if we have to initialise it to ok... 31 | } response; 32 | 33 | 34 | RestRequest::Response execute () 35 | { 36 | auto urlRequest = url.getChildURL (endpoint); 37 | bool hasFields = (fields.getProperties().size() > 0); 38 | if (hasFields) 39 | { 40 | MemoryOutputStream output; 41 | 42 | fields.writeAsJSON (output, 0, false, 20); 43 | urlRequest = urlRequest.withPOSTData (output.toString()); 44 | } 45 | 46 | std::unique_ptr input (urlRequest.createInputStream (hasFields, nullptr, nullptr, stringPairArrayToHeaderString(headers), 0, &response.headers, &response.status, 5, verb)); 47 | 48 | response.result = checkInputStream (input); 49 | if (response.result.failed()) return response; 50 | 51 | response.bodyAsString = input->readEntireStreamAsString(); 52 | response.result = JSON::parse(response.bodyAsString, response.body); 53 | 54 | return response; 55 | } 56 | 57 | 58 | RestRequest get (const String& endpoint) 59 | { 60 | RestRequest req (*this); 61 | req.verb = "GET"; 62 | req.endpoint = endpoint; 63 | 64 | return req; 65 | } 66 | 67 | RestRequest post (const String& endpoint) 68 | { 69 | RestRequest req (*this); 70 | req.verb = "POST"; 71 | req.endpoint = endpoint; 72 | 73 | return req; 74 | } 75 | 76 | RestRequest put (const String& endpoint) 77 | { 78 | RestRequest req (*this); 79 | req.verb = "PUT"; 80 | req.endpoint = endpoint; 81 | 82 | return req; 83 | } 84 | 85 | RestRequest del (const String& endpoint) 86 | { 87 | RestRequest req (*this); 88 | req.verb = "DELETE"; 89 | req.endpoint = endpoint; 90 | 91 | return req; 92 | } 93 | 94 | RestRequest field (const String& name, const var& value) 95 | { 96 | fields.setProperty(name, value); 97 | return *this; 98 | } 99 | 100 | RestRequest header (const String& name, const String& value) 101 | { 102 | RestRequest req (*this); 103 | headers.set (name, value); 104 | return req; 105 | } 106 | 107 | const URL& getURL() const 108 | { 109 | return url; 110 | } 111 | 112 | const String& getBodyAsString() const 113 | { 114 | return bodyAsString; 115 | } 116 | 117 | private: 118 | URL url; 119 | StringPairArray headers; 120 | String verb; 121 | String endpoint; 122 | DynamicObject fields; 123 | String bodyAsString; 124 | 125 | Result checkInputStream (std::unique_ptr& input) 126 | { 127 | if (! input) return Result::fail ("HTTP request failed, check your internet connection"); 128 | return Result::ok(); 129 | } 130 | 131 | static String stringPairArrayToHeaderString(StringPairArray stringPairArray) 132 | { 133 | String result; 134 | for (auto key : stringPairArray.getAllKeys()) 135 | { 136 | result += key + ": " + stringPairArray.getValue(key, "") + "\n"; 137 | } 138 | return result; 139 | } 140 | }; 141 | 142 | 143 | 144 | #endif // RESTREQUEST_H_INCLUDED 145 | -------------------------------------------------------------------------------- /juce_module_info: -------------------------------------------------------------------------------- 1 | { 2 | "id": "rest_request", 3 | "name": "rest_request", 4 | "version": "0.2.0", 5 | "description": "Module to simplify calls to HTTP REST APIs", 6 | "website": "https://github.com/adamski/RestRequest", 7 | "license": "Not Specified", 8 | "dependencies": [ 9 | { 10 | "id": "juce_core", 11 | "version": "4.1.0" 12 | } 13 | ], 14 | "include": "rest_request.h", 15 | "compile": [ 16 | { 17 | "file": "rest_request.cpp", 18 | "target": "! xcode" 19 | }, 20 | { 21 | "file": "rest_request.mm", 22 | "target": "xcode" 23 | } 24 | ], 25 | "browse": [ 26 | "Source/*" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /rest_request.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | The MIT License (MIT) 4 | 5 | Copyright (c) [year] [fullname] 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | */ 26 | 27 | 28 | #include "AppConfig.h" 29 | #include "rest_request.h" 30 | 31 | 32 | namespace adamski { 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /rest_request.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | The MIT License (MIT) 4 | 5 | Copyright (c) [year] [fullname] 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | */ 26 | 27 | /* 28 | BEGIN_JUCE_MODULE_DECLARATION 29 | ID: rest_request 30 | vendor: adamski 31 | version: 0.2.0 32 | name: RestRequest 33 | description: Simplify requests to HTTP REST and JSON APIs 34 | website: https://github.com/adamski/RestRequest 35 | dependencies: juce_core 36 | END_JUCE_MODULE_DECLARATION 37 | */ 38 | 39 | #pragma once 40 | #include "JuceHeader.h" 41 | 42 | namespace adamski { 43 | using namespace juce; 44 | 45 | #include "Source/RestRequest.h" 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /rest_request.mm: -------------------------------------------------------------------------------- 1 | 2 | #include "rest_request.cpp" 3 | 4 | --------------------------------------------------------------------------------