I am making a a roulette REST API in Golang:
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/gorilla/mux"
)
func handleRequests() {
// creates a new instance of a mux router
myRouter := mux.NewRouter().StrictSlash(true)
myRouter.HandleFunc("/spin/", handler).Methods("POST")
log.Fatal(http.ListenAndServe(":10000", myRouter))
}
func handler(w http.ResponseWriter, r *http.Request) {
reqBody, _ := ioutil.ReadAll(r.Body)
s := string(reqBody)
fmt.Println(s)
}
func main() {
fmt.Println("Rest API v2.0 - Mux Routers")
handleRequests()
}
main.go
And I am testing the POST method with a Python script:
import requests
url = 'http://localhost:10000/spin/'
myobj = {'bets':[
{
'amount' : 10,
'position' : [0,1,2]
},
{
'amount' : 20,
'position' : [10]
}
]
}
x = requests.post(url, data = myobj)
print(x.text)
test.py
When I run the test script. And the server receives my POST request. The request body is:
bets=amount&bets=position&bets=amount&bets=position
The problem is that the values for the 'amount' and 'position' keys are not there.
My question is - how can I make/ handle POST requests so that I am able to access the values for the embedded keys 'amount' and 'position' in my handler function on the Go server, so that I can put this information into an instance of a struct.
The problem lies on the python side, if you print out the body/header of your request:
print requests.Request('POST', url, data=myobj).prepare().body
print requests.Request('POST', url, data=myobj).prepare().headers
# bets=position&bets=amount&bets=position&bets=amount
# {'Content-Length': '51', 'Content-Type': 'application/x-www-form-urlencoded'}
data uses x-www-form-urlencoded encoding, so expects a flat list of key/value pairs.
You probably want json to represent your data:
print requests.Request('POST', url, json=myobj).prepare().body
print requests.Request('POST', url, json=myobj).prepare().headers
# {"bets": [{"position": [0, 1, 2], "amount": 10}, {"position": [10], "amount": 20}]}
# {'Content-Length': '83', 'Content-Type': 'application/json'}
Fix:
x = requests.post(url, json = myobj) // `json` not `data`
Finally, it's worth checking the Content-Type header on the Go server-side to ensure you get the encoding you expect (in this case application/json).
I think you need a struct to unmarshal the data.I think this code could help you.
package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"io/ioutil"
"log"
"net/http"
)
type Body struct {
Bets []Persion `json:"bets"`
}
type Persion struct{
Amount int `json:"amount"`
Position []int `json:"position"`
}
func handleRequests() {
// creates a new instance of a mux router
myRouter := mux.NewRouter().StrictSlash(true)
myRouter.HandleFunc("/spin/", handler).Methods("POST")
log.Fatal(http.ListenAndServe(":10000", myRouter))
}
func handler(w http.ResponseWriter, r *http.Request) {
reqBody, _ := ioutil.ReadAll(r.Body)
bodyObj :=&Body{}
err:=json.Unmarshal(reqBody,bodyObj)
if err!=nil{
log.Println("%s",err.Error())
}
//s := string(reqBody)
fmt.Println(bodyObj.Bets[0].Amount)
}
func main() {
fmt.Println("Rest API v2.0 - Mux Routers")
handleRequests()
}
Related
Hi I’m figuring out how to share Plex library in dart.
I'm helping myself with this working script in python ( it works)
https://gist.github.com/JonnyWong16/f8139216e2748cb367558070c1448636
unfortunately my code returns an http error 400, bad request
note: When I run the dart code there are no shared library.
maybe the payload is not correct :|
Thank for any help
import 'package:http/http.dart' as http;
class Server {
String token, ip, port;
Server(this.ip, this.port, this.token);
share() async {
var server_id = '00000000000000000000000000000000'; fake id
var library_section_ids = '97430074'; // right id , it works in python
var invited_id = '50819899'; // right id , it works in python
var headers = {
'Accept': 'application/json',
'X-Plex-Token': token,
};
var data =
'["server_id": $server_id,'
' "shared_server":["library_section_ids":[$library_section_ids],'
' "invited_id":$invited_id]';
var res = await http.post(
Uri.parse(
'https://plex.tv/api/servers/$server_id/shared_servers/'),
headers: headers,
body: data);
if (res.statusCode != 200) {
throw Exception('http.post error: statusCode= ${res.statusCode}');
}
print(res.body);
}
}
void main(List<String> arguments) async {
var srv = Server('xxx.yyy.xxx.yyy', '32400', '000000000-1111');
await srv.share();
}
The old code has a few bug and don't encode perfectly the data
I solved with 'dio' package and this link helped me a lot https://reqbin.com/
If the user has no shared library this code add a new one
import 'package:dio/dio.dart';
class Server {
String token;
Server(this.token);
test() async {
var serverId = '';
var librarySectionIds = ;
var invitedId = ;
var dio = Dio();
var data = {
"server_id": serverId,
"shared_server": {
"library_section_ids": librarySectionIds,
"invited_id": invitedId
}
};
dio.options.headers['Accept'] = 'application/json';
dio.options.headers["authorization"] = "Bearer $token";
var response = await dio.post(
'https://plex.tv/api/servers/$serverId/shared_servers/',
data: data);
print(response);
}
Check the two part of code bellow. There is two method second one is python method which make a post request to a url but i want to do same api call with same payload with c# restsharp. I already tried to convert code like bellow but since i don't have idea about python i am not able to understand how can i add payload as its done in python code. I already tried to add this payload using request.AddBody but it is not same as it was done in python code. How can i add those payload info with restsharp request exactly as done in py? please advice
payload:
data={
"locationType": "LOCATION_INPUT",
"zipCode": zip_code,
"storeContext": "generic",
"deviceType": "web",
"pageType": "Gateway",
"actionSource": "glow",
"almBrandId": "undefined",
}
C#
public static IRestResponse MakeApiCall(string zip_code)
{
var client = new RestClient("https://www.example.com");
var request = new RestRequest(Method.POST);
//request.AddHeader();//i can add header like this thats not a problem
//request.AddCookie();//i can add cookie like this thats not a problem
request.AddBody("data=", #"{" +
"locationType\": \"LOCATION_INPUT",
"zipCode\": zip_code,
"storeContext\": \"generic",
"deviceType\": \"web",
"pageType\": \"Gateway",
"actionSource\": \"glow",
"almBrandId\": \"undefined");
var result = client.Execute(request);
return result;
}
Python:
def MakeApiCall(zip_code: str, headers: dict, cookies: dict):
response = requests.post(
url="https://www.example.com",
data={
"locationType": "LOCATION_INPUT",
"zipCode": zip_code,
"storeContext": "generic",
"deviceType": "web",
"pageType": "Gateway",
"actionSource": "glow",
"almBrandId": "undefined",
},
headers=headers,
cookies=cookies,
)
assert response.json()["isValidAddress"], "Invalid change response"
return response.cookies
If I understood your question correctly, you are trying to convert the method from python into a C# method. I am assuming that you are using .NET Core and the RestSharp library, if not you need to clarify what you are using in your original post.
In your class instantiate the RestClient class in a constructor
public class RandomClass
{
private readonly IRestClient _client;
public RandomClass(){
_client = new RestClient("baseUrl");
_client.UseSerializer(
() => new JsonSerializer { DateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFZ" }
);
}
}
Now, define a class for your request data:
public class Location {
public string LocationType {get; set;}
public string ZipCode {get; set;}
public string StoreContext {get; set; }
public string DeviceType {get; set;}
public string ActionSource {get; set;}
public string BrandId {get; set;}
}
In your MakeApiCall method:
public IRestResponse MakeApiCall(Location data){
var request = _client.Request("/endpoint/relative/to/baseUrl", Method.POST);
var jsonToSend = JsonSerializer.Serialize(data);
request.AddParameter(
"application/json; charset=utf-8",
jsonToSend,
ParameterType.RequestBody
);
var response = _client.Execute(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response.";
throw new Exception(message, response.ErrorException);
}
// if we get to here then the request succeeded
return response.data;
}
I haven't tested it, but nonetheless it should point you in the right direction.
There are two ways to go about it.
Use a strongly typed data structure
Create a dynamic object and use that as your data object.
Create a class to store your data object
class MyDataType
{
[JsonProperty("locationType")]
public string LocationType { get; set; }
[JsonProperty("zipCode")]
public string ZipCode { get; set; }
//...
}
// and in your method, you would use the above datatype like this,
var data = new MyDataType
{
LocationType = "location",
ZipCode = "zipCode"
// ...
};
or 2. Create a dynamic / anonymous object and use that as json body.
var data = new
{
locationType = "location",
zipCode = "zipCode",
storeContext = "generic",
deviceType = "web",
pageType = "Gateway",
actionSource = "glow",
almBrandId = "undefined",
};
Once you have your object, I would recommend using AddJsonBody as AddBody is deprecated.
var client = new RestClient("https://www.example.com");
var request = new RestRequest(Method.POST);
request.AddHeader(#"Content-Type", #"application/json");
request.AddHeader(#"Accept", #"application/json");
request.AddJsonBody(data);
var result = client.Execute(request);
string actualData = result.Content;
result.Content would have your response. You can use Newtonsoft Json to convert data in your response to a class object and validate your data that way.
I want the following code to be translated into GAS from python. I wrote the GAS version pasted below but it is not working. It must be something simple but I don't know the reason why I get this error. Any advice will be appreciated. Thanks.
import requests
requestId = "*******************"
url = "http://myapi/internal/ocr/"+requestid+"/ng"
payload={}
headers = {
'X-Authorization': 'abcdefghijklmn'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
I wrote this at the moment but I get bad request error.
function sending(yesorno, requestId) {
var requestId = "*******************"
var STAGING_KEY = "abcdefghijklmn"
var url = url = "http://myapi/internal/ocr/"+requestId+"/ng"
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': JSON.stringify(data),
'headers': {
'X-Authorization': STAGING_KEY
}
};
//Error processing
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options));
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error')
}
}
Modified Code
function sending() {
var requestId = "*************************"
var STAGING_KEY = "abcdefghijklmn"
var url = "http://myapi/internal/ocr/"+requestId+"/ng";
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': data,
'headers': {
'X-Authorization': STAGING_KEY
}
};
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
Logger.log(response)
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error1')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error2: '+ e.toString())
}
}
Error
error2: Exception: Bad request:
I understood your situation as follows.
Your python script works fine.
You want to convert the python script to Google Apps Script.
When your Google Apps Script is run, an error Exception: Bad request: occurs.
In this case, how about the following modification? When response = requests.request("POST", url, headers=headers, data=payload) is used with payload={}, I think that at Google Apps Script, it's 'payload': {}.
Modified script:
function sending() {
var requestId = "*******************"
var STAGING_KEY = "abcdefghijklmn"
var url = "http://myapi/internal/ocr/" + requestId + "/ng"
var data = {}
var options = {
'muteHttpExceptions': true,
'method': 'post',
'payload': data,
'headers': {
'X-Authorization': STAGING_KEY
}
};
try {
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());
console.log(response)
if (response && response["id"]) {
return 'sent';
} else {
//reportError("Invalid response: " + JSON.stringify(response));
//return 'error';
Logger.log('error')
}
} catch (e) {
//reportError(e.toString());
//return 'error';
Logger.log('error')
}
}
Note:
By the above modification, the request of Google Apps Script is the same as that of the python script. But if an error occurs, please check the URL and your STAGING_KEY, again. And, please check whether the API you want to use can access from the Google side.
Reference:
fetch(url, params)
Here is a graphql query with its result : OK.
I try to get the same result with Python, but I get nothing : response.text is empty. (API key is not needed).
q = """
{
node(id: "UXVlc3Rpb25uYWlyZTo5NTNjYjdjYS0xY2E0LTExZTktOTRkMi1mYTE2M2VlYjExZTE=") {
... on Questionnaire {
replies(first: 10, after: null) {
totalCount
pageInfo {
hasNextPage
endCursor
}
edges {
node {
id
createdAt
publishedAt
updatedAt
author {
id
}
responses {
question {
title
}
... on ValueResponse {
value
}
}
}
}
}
}
}
}
"""
response = requests.post(url = "https://granddebat.fr/graphql" , json = {'query': q})
print(response.text)
Please, any idea ?
It's all good with the query itself. In request you need to pass headers with {'Accept':
'application/vnd.cap-collectif.preview+json'}
response = requests.post(
url = "https://granddebat.fr/graphql",
json = {'query': q,},
headers= {'Accept': 'application/vnd.cap-collectif.preview+json'}
)
This question already has answers here:
Reactjs, Super expression must either be null or a function
(2 answers)
Closed 5 years ago.
So I'm new to React and even though I've found multiple others having the same issue, I still haven't found the error in my code. Therefore I turn to you stackoverflow, you're my only hope!
I am learning, so I wanted to create a simple ReactJS application that handles a HTTP-request. After finishing the code I encountered the error:
Uncaught TypeError: Super expression must either be null or a function, not object
at exports.default (inherits.js?0578:21)
at eval (app.js?71f7:22)
The error persists even though I've tried a lot of different changes and I am fairly certain that it's related to imports/exports as this is what a lot of other sources tell me, although double-checking imports etc. hasn't yielded any results.
The code:
app.js ( handles the rendering of a simple button and should execute a simple GET request on click )
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { createServerSagaRequest } from '../saga/serverSaga'
import { incrRequestAmount, requestSelector } from '../reducer/requestReducer'
const mapStateToProps = (state) => {
return {
getRequestAmount: requestSelector.requests(state),
}
}
const mapDispatchToProps = (dispatch) => {
return {
open: (url, data, action, method) => dispatch(createServerSagaRequest((url, data, action, method))),
requests: () => dispatch(incrRequestAmount()),
}
}
class App extends React {
constructor(props){
super(props)
}
_buttonClick() {
this.props.requests()
this.props.open("http://mvctestproject.local/GetData", "TestDataFraGet", action, "GET")
}
render(){
return (
<button
className="btn btn-default"
onClick={this._buttonClick()}>{this.props.getRequestAmount()}
</button>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
serverSaga.js (my saga which can access the reducer and service)
import React, { Component } from 'react'
import { put, call, take, fork, select } from 'redux-saga/effects'
import { callServer } from '../service/serverService'
import { incrRequestAmount, requestSelector } from '../reducer/requestReducer'
export function createServerSagaRequest() {return { type: CREATE_REQUEST }}
function* handleRequest(url, data, action, method, success){
incrRequestAmount()
return yield executeRequest(url, data, action, method, success)
}
function* executeRequest(url, data, action, method, success) {
let response = yield call(callServer, url, method, data)
let responseSuccess = response && response.Succeeded
return
}
export default function* serverSaga(){
yield [
fork(function*(){
yield call (CREATE_REQUEST, handleRequest)
}),
]
}
rootSaga.js ( grouping sagas - in case I made more )
import { fork } from 'redux-saga/effects'
import serverSaga from './serverSaga'
export default function* rootSaga(){
yield [
fork(serverSaga)
]
}
requestReducer.js ( only function is to increment a variable after each request)
import { fromJS } from 'immutable'
export function incrRequestAmount() {return {type: 'INCR_REQUESTS'}}
const initialState = {
requestAmount: 0
}
function requestReducer(state = fromJS(initialState), action){
switch(action.type){
case 'INCR_REQUESTS':
return state.updateIn(["requestAmount"], (requests) => requests++)
default:
return state
}
}
export const requestSelector = {
amount: state => state.requests.get('requestAmount')
}
export default requestReducer
reducers.js ( grouping reducers - in case i made more )
import { combineReducers } from 'redux'
import React, { Component } from 'react'
import requests from './requestReducer'
export default combineReducers({
requests,
})
serverService.js ( handles calls to the server (GET/POST)
import React, { Component } from 'react'
export function callServer(url, bodyData, method){
let methodType = method.toLowerCase()
return new Promise((resolve, reject) => {
let r;
switch (methodType){
case 'post':
r = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(bodyData)
}
break;
case 'get':
r = {
method: 'GET'
}
break;
}
if (r) {
console.log("URL: ", url)
fetch(url, r)
.then((response) => {
console.log("Resp: ", url, response)
return response.json()
})
}
})
}
You need to extend React.Component to create a component, not React itself:
class App extends React {
should be
class App extends React.Component {
, or since you imported Component directly
class App extends Component {