I'm using huandu/facebook for Golang to access the FB API. https://github.com/huandu/facebook
This works really well locally but when I try to run from the Google App Engine environment, I can't get it to run.
I used this code locally:
res, err := fb.Get("/me", fb.Params{
"fields": "id,first_name,last_name,name",
"access_token": usertoken,
})
In the documentation (link above) they do mention the App Engine environment but I can'f figure out how to ge this to work with the fb.Get convention.
Thanks.
Edit
Almost got it to work!:
// create a global App var to hold app id and secret.
var globalApp = fb.New("<appId>", "<appSecret>")
session := globalApp.Session(usertoken) //User token here
context := appengine.NewContext(r) //Not sure what r should be...
session.HttpClient = urlfetch.Client(context)
res, err := session.Get("/me", nil)
if err := json.NewEncoder(w).Encode(res); err != nil {
panic(err)
}
If I do this I get back the Id and name. Now all I need to do is request the other parameters. Do I do this in the r parameter to the app engine context?
To answer the last question asked, the appengine.NewContext(r) function takes a *http.Request as a parameter, but this refers to the current request, the one your code is executing in. You can use r.URL.Query() if you wanted to get the query parameters that were sent to this request.
If you want to send parameters in another request, like the one to the Facebook API, you can include them directly in the URL you pass to session.Get(). You can use url.Values.Encode if you want to build a query string from a map of values. If you need to make a request using a method other than GET, such as to an API method that expects JSON, you can use http.NewRequest eg.
session.HttpClient = urlfetch.Client(context)
request, err := http.NewRequest("PUT", url, strings.NewReader("{ "someProperty": 1234 }"))
response, err := session.Do(request)
Related
I wonder how to handle endpoint with given empty parameter, for example one endpoint of my API is
...url/item/{id}
and it's implementation is
func GetItem(c *gin.Context){
id := c.Param("id")
...
}
Should I handle empty id by
if id == ""{
//handle if empty
return
}
or it's not necessary to validate it?
I think about it because you can call endpoint method from unit test and the question is if it's possible to hack it somehow and call endpoint with empty id, which may cause some fatal errors?
You should prevent it at your routing layer rather than when you're getting the path parameters.
router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
In this snippet from the gin documentation it basically describes a similar get endpoint where it expects you to have a :name parameter, which maps to your id parameter. If the route is invoked without an id parameter it'll not route to that function.
If I authenticate to D365 via the web browser, and then enter the following URL:
https://mytenantcode.crmserver.dynamics.com/api/data/v8.2/systemusers?$select=systemuserid,lastname,firstname,title&$top=3
I can get back the top 3 records with the data I requested.
I seem to be able to authenticate to D365 in code as per my other question (which I answered), and have an access token but I cannot seem to be able to determine how to setup the TRESTRequest object so that the Execute works.
Currently, it always returns a 401 Unauthorized error.
I've tried setting the TOAuth2Authenticator.AccessToken property to the token I received from D365, and then set the TRESTClient.Authenticator property to the TOAuth2Authenticator and the TRESTQuest.Client to the TRESTClient, which is how the examples work in the RESTDemos project, but I still get 401.
This is the last example of the code I tried, that should have worked, given that all the REST objects are linked correctly:
RESTClient.BaseURL := 'https://**mytenantcode**.**crmserver**.dynamics.com/api/data/v8.2/';
RESTRequest.Method := TRESTRequestMethod.rmGET;
RESTRequest.Resource := 'systemusers?$select={SELECT}&$top={TOP}';
RESTRequest.AddParameter('SELECT', 'systemuserid,'+
'lastname,'+
'firstname,'+
'title');
RESTRequest.AddParameter('TOP', '3');
RESTRequest.Execute;
I finally got it to return the correct information using the following code for calling the Web API:
RESTClient.BaseURL := 'https://mytenantcode.crmserver.dynamics.com/';
RESTRequest.Resource := 'api/data/v8.2/systemusers?$select=int_staffnumber,'+
'_int_serviceareaid_value,'+
'_territoryid_value,'+
'lastname,'+
'firstname,'+
'systemuserid,'+
'title';
RESTRequest.AddAuthParameter('Authorization', 'Bearer ' + AToken, TRESTRequestParameterKind.pkHTTPHEADER,
[TRESTRequestParameterOption.poDoNotEncode]);
RESTRequest.Execute;
The important change was the addition of the Authorization header parameter, and not using the Params for the query parameters as it seems the REST Client Library doesn't actually do it correctly.
Also had to change the ResourceURI for the token authorization to match the https://mytenantcode.crmserver.dynamics.com URL being used for the method call.
I'm working on a DElphi FMX project where I make a lot of requests to a REST backend.
I'm using one TRESTClient, and are dynamically creting a TRESTRequest every time I ask for something, my plan is to make it multitreading to make the UI be more responsive.
I have made a function called DoRequest, that do the actual request, it looks like something this:
Function TFormMain.Dorequest(Meth:TRESTRequestmethod;Url,RequestBody:String;
Var Respons: TCustomRESTResponse):Boolean;
Var
par: TRESTRequestParameter;
Req : TRESTRequest;
begin
Req := TRESTRequest.Create(RESTClient);
With Req do
try
if RequestBody<>'' then
begin
Params.Clear;
par := Params.AddItem('body',RequestBody);
par.ContentType := ctAPPLICATION_JSON;
par.Kind := pkREQUESTBODY;
end;
Method := Meth;
Resource := Url;
Execute;
Respons := Response;
Result := Respons.StatusCode In [200,201];
finally
Req.Free; // <-Error here
end;
end;
I call it like this:
procedure TFormUser.Button1Click(Sender: TObject);
Var
Respons: TCustomRESTResponse;
begin
If DoRequest(rmPOST,CreateUserUrl,JSON,Respons) then
begin
ShowMessage('User '+EdEmail.Text+' created');
ModalResult := MrOk;
end
However, I get an Acces Violation when freeing Req, my TRESTRequest.
I found out that it is because the TCustomRESTResponse Respons is just made a pointer to the memory where the Req.Response is placed, so freeing Req also destroys Respons.
My question is: How do I make a copy of Req.Response that lives after Req is freed?
I have tried Respons.Assign(Response), but it gives the rather strange error: "Cannot assign a TCustomRESTResponse to a TFormMain"
Am I doing this the wrong way, also keeping in mind that I would like the actual request to be in another tread?
Michael
When you don't link your own TRESTResponse to the client, the client will create one of its own and also free it. If you create your own TRESTResponse and assign it, the client will leave it alone, and you can free it whenever you want.
That said, like I mentioned in the comment, I think it's probably better to let the thread deal with deserializing the response, and have it pass a more generic class or record holding the relevant information (a value object, if you're into that), rather than passing around the specific TRESTResponse.
answered
I am having a hard time with Mongodb and Gridfs, using it with Go's http package. I am trying to store a .mp4 file into Gridfs, then pull it out into the browser for playback.
Heres what I am doing now. It successfully pulls the file from
database, I could even write it correctly to a download location.
// Connect to database
// Session to database
func movie(w http.ResponseWriter r *http.Request) {
file, err := db.GridFS("fs").Open("movie.mp4")
if err != nil {
log.Println(err)
}
defer file.Close()
w.Header.Set("Content-type", "video/mp4")
if _, err := io.Copy(w, file); err != nil {
log.Println(err)
}
// I am trying to send it to the browser.
// I want to achieve same thing as, http://localhost/view/movie.mp4,
as if you did that.
}
If the file was on the server, I would just do something like this. But instead I am trying to store it in Mongodb, for all around easier use involving metadata.
func movie(w http.ResponseWriter r *http.Request) {
http.ServeFile("./uploads/movie.mp4") // Easy
}
The browser is receiving something, but its just malformed or corrupted. Just shows the video player with an error message. Any help would be appreciated, I have only been programming a week.
Here is a picture of the error, no console error messages.
Unless someone has an alternative to storing video files for playback
in browser somewhere other than MongoDB or Amazon S3. Please let me know,
thanks.
You may want to check http.ServeContent. It will handle all the mess (content-type, content-length, partial data, cache) automaticlly and save you a lot of time. It takes a ReadSeeker to serve, which GridFile already implented. So your code may simply change to the below.
func movie(w http.ResponseWriter r *http.Request) {
file, err := db.GridFS("fs").Open("movie.mp4")
if err != nil {
log.Println(err)
}
defer file.Close()
http.ServeContent(w,r,"movie.mp4",file.UploadDate(),file)
}
If that doesn't work, please use tools like curl or wget to download the served content and compare it to the orignal one (in db).
I'm trying to get some facebook current user basic information.
Here is my code. (It's Oracle PL/SQL)
URL := 'http://graphm-facebook.maxapex.ws/me?fields(id,name,email)&access_token=' || Token;
Method := 'GET';
Response := apex_web_service.make_rest_request(p_url => URL, p_http_method => Method);
But I'm getting the html answer : 503 Service Temporarily Unavailable
I'm sure it's not related to any service unavailability. Because when I run the following command, it works successfully.
URL := 'http://graphm-facebook.maxapex.ws/me?access_token=' || Token;
Can anyone help please ? Thanks.