Facebook Graph API post displaying some message characters incorrectly - facebook-graph-api

I'm attempting to post a message to a users wall using the facebook graph api.
https://graph.facebook.com/me/feed
Charchters like å, ä or ö would display incorrectly with symbols like ���...
I used apacheCommons StringEscapeUtils.encodeHtml around all the relevent parameters sent in the request (message, name, description).
def params = [
accessToken: getFacebookAccessToken(),
message: StringEscapeUtils.escapeHtml(deal.title),
pictureUrl: imageUrl,
name: StringEscapeUtils.escapeHtml(deal.title),
description: StringEscapeUtils.escapeHtml(deal.shortDescription),
actionLabel: StringEscapeUtils.escapeHtml(actionLabel),
actionUrl: actionUrl
]
def graph(path, params, method = GET, contentType = JSON) {
def http = null
http = new TrustAllHttpBuilder(ConfigurationHolder.config.facebook.graph.uri)
http.request( method, contentType) { req ->
uri.path = path
req.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES );
req.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout );
req.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, socketTimeout );
requestContentType = URLENC
body = params
response.success = { resp, obj ->
return obj
}
}
}
The "Name" and "Description" display correctly in facebook after this change but the "Message" still does not render correctly.
Any ideas why the "Message" is not displaying correcltly?
Does FB handle it differently?
Thanks
Update
I adjusted the params to be URLEncoded to UTF-8 before sending in the body of JSON request.
def params = [
accessToken: getFacebookAccessToken(),
message: URLEncoder.encode(deal.title,"UTF-8"),
pictureUrl: imageUrl,
name: URLEncoder.encode(deal.title,"UTF-8"),
description: URLEncoder.encode(deal.shortDescription,"UTF-8"),
actionLabel: URLEncoder.encode(actionLabel,"UTF-8"),
actionUrl: actionUrl
]
The Request:
14:49:13 DEBUG [FacebookService] body: Message: Tommy+%C3%80%C3%84%C4%87%C3%95,Name: Tommy+%C3%80%C3%84%C4%87%C3%95,Description: %C3%80%C3%84%C4%87%C3%95%C3%80%C3%84%C4%87%C3%95,Caption: ,Action Label: TEST,ActionUrl: http://www.mytest.com
14:49:51 DEBUG [FacebookService] Calling facebook graph API https://graph.facebook.com/me/feed
14:49:51 DEBUG [TrustAllHttpBuilder] POST https://graph.facebook.com/me/feed
14:49:52 DEBUG [headers] >> POST /me/feed HTTP/1.1
14:49:52 DEBUG [headers] >> Accept: application/json, application/javascript, text/javascript
14:49:52 DEBUG [headers] >> Content-Length: 475
14:49:52 DEBUG [headers] >> Content-Type: application/x-www-form-urlencoded; charset=windows-1252
14:49:52 DEBUG [headers] >> Host: graph.facebook.com
14:49:52 DEBUG [headers] >> Connection: Keep-Alive
14:49:53 DEBUG [headers] << HTTP/1.1 200 OK
14:49:53 DEBUG [headers] << Access-Control-Allow-Origin: *
14:49:53 DEBUG [headers] << Cache-Control: private, no-cache, no-store, must-revalidate
14:49:53 DEBUG [headers] << Content-Type: application/json
14:49:53 DEBUG [headers] << Expires: Sat, 01 Jan 2000 00:00:00 GMT
14:49:53 DEBUG [headers] << Pragma: no-cache
14:49:53 DEBUG [headers] << X-FB-Rev:
14:49:53 DEBUG [headers] << X-FB-Debug:
14:49:53 DEBUG [headers] << Date: Fri, 05 Oct 2012 13:49:52 GMT
14:49:53 DEBUG [headers] << Connection: keep-alive
14:49:53 DEBUG [headers] << Content-Length: 40
The Result in FB (Not working):

escapeHtml is the wrong method for that – you see how your message is now showing HTML Entities. You do not want to post HTML code, you want to post plain text.
Charchters like å, ä or ö would display incorrectly with symbols like ���...
That’s most likely because your application is using the wrong character encoding.
Make sure to use UTF-8. (Or convert your parameter values to UTF-8 before passing them to the API, should the former not be possible.)
Edit:
I tried converting the params to UTF-8 before
14:49:13 DEBUG [FacebookService] body: Message: Tommy+%C3%80%C3%84%C4%87%C3%95,Name: …
These are URL-encoded UTF-8 characters. URL-encoding is contra-productive here.
14:49:52 DEBUG [headers] >> Content-Type: application/x-www-form-urlencoded; charset=windows-1252
Thou shalt not Lie into the API’s Face so blatantly :-)
Seriously, find out what brings your app to send that charset in the request header – and see how you get that changed to UTF-8 as well (or to leave the charset part out completely).

It turns out theEncoderRegistry class already
has a charset field that it uses for the request data. It defaults to
the platform encoding. You can set it to UTF-8 as follows:
def graph(path, params, method = GET, contentType = JSON) {
def http = null
http = new TrustAllHttpBuilder(ConfigurationHolder.config.facebook.graph.uri)
http.encoderRegistry = new EncoderRegistry( charset: 'utf-8' )
http.request( method, contentType) { req ->
uri.path = path
req.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES );
req.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout );
req.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, socketTimeout );
requestContentType = URLENC
body = params
response.success = { resp, obj ->
return obj
}
}
}
Answer reference

Related

Power BI REST API BadRequest for measures

I have created a dataset without major incidence
{\"tableName\": \"Sales\"
,\"columns\": [
{\"name\":\"ProductID\", \"dataType\":\"int64\", \"summarizeBy\":\"none\", \"isHidden\":\"True\", \"formatString\":\"#,##0\"}
, {\"name\":\"Date\", \"dataType\":\"DateTime\", \"formatString\":\"dd/mm/yyyy\"}
, {\"name\":\"TipID\", \"dataType\":\"int64\", \"summarizeBy\":\"none\", \"isHidden\":\"True\", \"formatString\":\"#,##0\"}
, {\"name\":\"Sales\", \"dataType\":\"double\", \"formatString\":\"#,##0\"}
]
}
, but when I try to put some measure, always get a "BadRequest".
{\"tableName\": \"Sales\"
,\"columns\": [
{\"name\":\"ProductID\", \"dataType\":\"int64\", \"summarizeBy\":\"none\", \"isHidden\":\"True\", \"formatString\":\"#,##0\"}
, {\"name\":\"Date\", \"dataType\":\"DateTime\", \"formatString\":\"dd/mm/yyyy\"}
, {\"name\":\"TipID\", \"dataType\":\"int64\", \"summarizeBy\":\"none\", \"isHidden\":\"True\", \"formatString\":\"#,##0\"}
, {\"name\":\"Sales\", \"dataType\":\"double\", \"formatString\":\"#,##0\"}
]
, \"measures\": [
{\"name\": \"TrySales\", \"expression\": \"SUM(Sales[Sales])\"}
]
}
I have created a "Push Dataset" where only add measures, with the same error.
HttpContent body = new StringContent(postBody);
body.Headers.ContentType = new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json");
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
HttpResponseMessage response = client.PutAsync(restUri, body).Result;
JSON
{\"tableName\": \"Sales\"
, \"measures\": [
{\"name\": \"TrySales\", \"expression\": \"CALCULATE(SUM(Ventas[Venta]);SUM(Sales[Sales])\"}
]
}
I only found an example code in this link..
The result from the PUT
Headers
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Pragma: no-cache
Transfer-Encoding: chunked
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: deny
X-Content-Type-Options: nosniff
RequestId: 6aa4198c-8315-4517-8f78-b5f90e6d1375
Access-Control-Expose-Headers: RequestId
request-redirected: true
home-cluster-uri: https://wabi-europe-north-b-redirect.analysis.windows.net/
Cache-Control: no-store, must-revalidate, no-cache
Date: Fri, 15 Nov 2019 13:08:36 GMT
Content-Type: application/json; charset=utf-8
}}
Request message
{Method: PUT, RequestUri: 'https://api.powerbi.com/v1.0/myorg/groups/1cd4f3cf-xxxx-41dd-83e4-c17708511d79/datasets/35b36723-ed24-xxxx-8e54-fc8e3a1503fe/tables/Sales'
, Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
Accept: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkJCOE...
Content-Type: application/json
Content-Length: 147
}}
Any suggestions?
EDIT
Response
Id = 37, Status = RanToCompletion
, Method = "{null}"
, Result = "{\"error\":{
\"code\":\"BadRequest\"
,\"message\":\"Bad Request\"
,\"details\":[
{\"message\":\"The property 'tableName' does not exist on type 'Microsoft.PowerBI.ServiceContracts.Api.Table'
. Make sure to only use property names that are defined by the type.\"
,\"target\":\"tableSchema\"}
]
}
}
It seems a spelling error due to an error in the documentation. In this link it appears as "tableName" and I have not found any more examples.
It is an error in the documentation.
This example in the documentation has tableName in the json. However, when you click on Try it the body has name.
Using name instead of tableName worked for me.

Accessing request data object

I am sending the following post Data to django Rest API
Request URL: http://localhost:8000/polls/
Request Method: POST
Status Code: 200 OK
Remote Address: 127.0.0.1:8000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:8100
Content-Length: 90
Content-Type: text/html; charset=utf-8
Date: Mon, 18 Jun 2018 11:01:54 GMT
Server: WSGIServer/0.2 CPython/3.6.5
Vary: Origin
X-Frame-Options: SAMEORIGIN
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 83
content-type: text/plain
Host: localhost:8000
Origin: http://localhost:8100
Referer: http://localhost:8100/
User-Agent: Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Mobile Safari/537.36
0:
{id: "1", username: "admin", password: "admin", user_group_id: "1", status: "1"}
The sent here will first be authenticated against the one saved in the database. I am trying to access this data but failing to do so .
When I process the data using json parse
case 1.
def dunction(request)
data = json.loads(request.body.decode("utf-8"))
vak=data
return HttpResponse(vak)
Then the following response is received
{'id': '1', 'username': 'admin', 'password': 'admin', 'user_group_id': '1', 'status': '1'}
case 2.
When manipulating the same code
data = json.loads(request.body.decode("utf-8"))
vak=data[0]
return HttpResponse(vak)
received response
idusernamepassworduser_group_idstatus
Case 3.
def dunction(request):
data = json.loads(request.body.decode("utf-8"))
vak=data.username
return HttpResponse(vak)
throws error 'list' object has no attribute 'username'
FYI,
Here I am trying to create a custom authentication function which authenticates the userData and then sends data back to the server.
'DEFAULT_AUTHENTICATION_CLASSES':
'polls.authentication.UserAuthentication',
HttpResponse takes an iterable. You are passing it various things that are in fact iterable: in the first case, a list, so it prints the (only) entry in that list, which is a dictionary; in the second case, you pass it a dict, so it iterates through the dict which gives the keys only. In the third case, for some reason you try and use object notation to access a key of a dict which is inside a list, which won't work at all.
I'm not sure what your actual question is, but if you do want to access the username you would need data[0]['username'].
Note though that the point of DRF is to abstract away a lot of this stuff; you should use the built-in functionality rather than doing any of this.
Use request.data to get the data for processing. return message along with HTTP status code like below
def dunction(request):
username=request.data['username']
password=request.data['password']
group_id=request.data['user_group_id']
status=request.data['status']
return Response({"status":"success"}, status=status.HTTP_200_OK)

Empty Body in Vapor Client GET Response

I'm trying to connect to
Bamboo HR's API, and I've managed to make this work with curl and Swift Foundation's URLRequest/URLSession (as well as an older Express node.js app).
However, when trying to utilize Vapor's client with the .get() method, I'm getting a successful 200 response from BambooHR - but the response's .body is empty.
Here's the code snippet:
key and {myDomain} are placeholders in the example
let encodedKey = "\(key):x".utf8.base64String
let directoryRootUrl = "https://api.bamboohr.com/api/gateway.php/{myDomain}/v1/employees/directory"
let response = try drop.client.get(
directoryRootURL,
headers: [
"Accept": "application/json",
"Authorization": "Basic \(encodedKey)",
"Host": "api.bamboohr.com"
])
When I do print(response), this is what's displayed:
Response
- HTTP/1.0 200 OK
- Headers:
Connection: close
Vary: User-Agent
Server: Apache
Content-Security-Policy: {...}
Date: Mon, 16 Jan 2017 00:26:31 GMT
Content-Type: application/json
X-Content-Type-Options: nosniff
- Body:
I'm wondering if I'm doing anything wrong with Vapor, or if it's a bug.
Like tobygriffin suggested, setting:
drop.client = FoundationClient.self
after creating the Droplet worked.

HTTP/1.1 401 Unauthorized in Response Headers in Load runner for GET Requests

I am new to Load runner , Am facing am issue while play back of the script
LR 12.50
O.S Windows 7 SP2
Protocol is Mobile HTTP/HTML
Recording mode is Proxy
Let me explain my scenario
While executing following function:
web_custom_request("authenticate",
"URL=https://ws-xx.xxx.com/tcs/rest/authenticate?include=user,company",
"Method=POST",
"Resource=0",
"RecContentType=application/json",
"Referer=",
"Snapshot=t1.inf",
"Mode=HTTP",
"EncType=application/json",
"Body={\"password\":\"xxx\",\"username\":\"xxx\",\"version\":\"1.0.40\"}",
LAST);
For the above POST method , am getting response as below
HTTP/1.1 200 OK\r\n
Date: Tue, 13 Oct 2015 19:19:21 GMT\r\n
Server: Apache-Coyote/1.1\r\n
Content-Type: application/json\r\n
Set-Cookie: dtCookie=DBE9311E44E5C47902702DC762030583|TXlBcHB8MQ; Path=/;
Domain=.xxx.com\r\n
Connection: close\r\n
Transfer-Encoding: chunked\r\n
Which is fine ,Now the second custom request is shown below
web_custom_request("profiles",
"URL=https://ws-test.xxx.com/tcs/rest/profiles",
"Method=GET",
"Resource=1",
"RecContentType=application/json",
"Referer=",
"Snapshot=t2.inf",
LAST);
For the above GET requests in the replay logs am getting:
401 unauthorized error.
GET /tcs/rest/profiles HTTP/1.1\r\n
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)\r\n
Accept: */*\r\n
Connection: Keep-Alive\r\n
Host: ws-test.xxx.com\r\n
Cookie: dtCookie=DBE9311E44E5C47902702DC762030583|TXlBcHB8MQ\r\n
\r\n
t=5921ms: 172-byte response headers for "https://ws-test.xxx.com/tcs/rest/profiles" (RelFrameId=1, Internal ID=2)
HTTP/1.1 401 Unauthorized\r\n
Date: Tue, 13 Oct 2015 19:19:22 GMT\r\n
Server: Apache-Coyote/1.1\r\n
Content-Type: application/json\r\n
Connection: close\r\n
Transfer-Encoding: chunked\r\n
\r\n
t=5922ms: 4-byte chunked response overhead for "https://ws-test.xxx.com/tcs/rest/profiles" (RelFrameId=1, Internal ID=2)
8b\r\n
t=5923ms: 139-byte chunked response body for "https://ws-test.xxx.com/tcs/rest/profiles" (RelFrameId=1, Internal ID=2)
{"errors":[{"message":"Authentication required to access endpoint","status":"401","code":"
NotAuthenticated","header":"Not Authenticated"}]}
I refereed this link.
My understanding from the above custom request , login is success but the next
subsequent requests are getting failed.
I have used web_cleanup_cookies() function but didn't solve the issue .
I tried to capture the Cookie ID using the below function
web_reg_save_param("COOKIE_ID",
"LR= Cookie: dtCookie=" ,
"RB= |TXlBcHB8MQ\r\n",
"Ord=All",
"RelFrameId=1",
"Search=All",
LAST);
web_add_header("Cookie",lr_eval_string("{COOKIE_ID}"));
Now question is where to place parameter "COOKIE_ID" in my script while there is
no value in script for COOKIE_ID?
How to handle this issue ? Can anybody please help me .
Please add below headers to the script
web_set_sockets_option("SSL_VERSION","TLS");
web_set_user("username", "password", "domain:portno" );
web_set_sockets_option("INITIAL_BASIC_AUTH","1");
In Vugen, Select snapshot view and compare both record and replay requests, suspecting there might be a missing of header in replay request.
If cookie is the only thing changing you can add it by using web_add_cookie function.

Directory API: delete member API operation fails for non-Google accounts

We are noticing that group members cannot be removed using the new Directory API if they are not Google accounts. We've tested this with both Dito GAM (note I am the author of GAM) and the Google API Explorer.
The operation functions correctly if the member to be removed is a Google account:
C:\gam-64>gam update group group99#jay.powerposters.org remove google-user#jay.powerposters.org
removing google-user#jay.powerposters.org
connect: (www.googleapis.com, 443)
send: 'DELETE /admin/directory/v1/groups/group99#jay.powerposters.org/members/google-user#jay.powerposters.org?quotaUser=1ee51612c9a0220af0cf5516a990b206e2a619e8&prettyPrint=true
HTTP/1.1
Host: www.googleapis.com
content-length: 0
authorization: Bearer <valid access token>
accept-encoding: gzip, deflate
accept: */*
user-agent: Dito GAM 3.01 / jay#ditoweb.com (Jay Lee) / Python 2.7.5 final / Windows-7-6.1.7601-SP1 AMD64 / google-api-python-client/1.2 (gzip)
reply: 'HTTP/1.1 204 No Content
header: Cache-Control: no-cache, no-store, max-age=0, must-revalidate
header: Pragma: no-cache
header: Expires: Fri, 01 Jan 1990 00:00:00 GMT
header: Date: Wed, 28 Aug 2013 12:57:06 GMT
header: ETag: "cZnI-gy4eI-n1-_cqk7okAteLZk/vyGp6PvFo4RvsFtPoIWeCReyIC8"
header: Server: GSE
this is the expected behavior. However, if the account to be removed is not a Google Account (Google Apps or consumer), an error is returned:
C:\gam-64>gam update group group99#jay.powerposters.org remove not-a-google-account#not-a-google-domain.com
removing not-a-google-account#not-a-google-domain.com
connect: (www.googleapis.com, 443)
send: 'DELETE /admin/directory/v1/groups/group99#jay.powerposters.org/members/not-a-google-account#not-a-google-domain.com?quotaUser=1ee51612c9a0220af0cf5516a990b206e2a619e8&prettyPrint=true
HTTP/1.1
Host: www.googleapis.com\r\ncontent-length: 0
authorization: Bearer <valid oauth 2.0 token>
accept-encoding: gzip, deflate
accept: */*
user-agent: Dito GAM 3.01 / jay#ditoweb.com (Jay Lee) / Python 2.7.5 final / Windows-7-6.1.7601-SP1 AMD64 / google-api-python-client/1.2 (gzip)
reply: 'HTTP/1.1 400 Bad Request
header: Content-Type: application/json; charset=UTF-8
header: Content-Encoding: gzip
header: Date: Wed, 28 Aug 2013 13:00:02 GMT
header: Expires: Wed, 28 Aug 2013 13:00:02 GMT
header: Cache-Control: private, max-age=0
header: X-Content-Type-Options: nosniff
header: X-Frame-Options: SAMEORIGIN
header: X-XSS-Protection: 1; mode=block
header: Content-Length: 122
header: Server: GSE
body: {
"error": {
"errors": [
{
"domain": "global",
"reason": "badRequest",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request"
}
}
Error 400: Bad Request - badRequest
Note that this same behavior shows in the Google API Explorer also:
http://screencast.com/t/fQZCnMYYs
https://developers.google.com/apis-explorer/#s/admin/directory_v1/directory.members.delete?groupKey=group99%2540jay.powerposters.org&memberKey=not-a-google-account%2540not-a-google-domain.com&_h=1&
It should be possible to remove ANY address from a Google Group via the Directory API
I spoke with Google Enterprise support about this and they acknowledged this was a bug (as Silvano has here). After speaking with the dev team, they told me that a work around for this is to delete using the ID of the user instead of email address.
A quick example of how you can delete all members using member ids.
Directory directory =
new Directory.Builder(httpTransport, jsonFactory, credentials)
.setApplicationName(APPLICATION_NAME)
.build();
Members members = directory.members().list(groupKey).execute();
for(Member member : members.getMembers()) {
String memberId = member.getId();
Delete delete = directory.members().delete(groupKey, memberId);
delete.execute();
}
Hope this helps until they can release a fix.
Google has resolved this issue on their end. Removing non-Google email addresses from a Google Group now works without issue.
Here is a working example in PHP with Add and Delete.
function gmail_provision($email, $email_list, $requested_operation) {
// requested_operation should be either add or delete
require_once "google-api-php-client/src/Google_Client.php";
require_once "google-api-php-client/src/contrib/Google_DirectoryService.php";
require_once "google-api-php-client/src/contrib/Google_Oauth2Service.php";
session_start();
$group_scope = 'https://www.googleapis.com/auth/admin.directory.group';
$service_account_email = '.....#developer.gserviceaccount.com';
$service_account_pkcs12_file_path = '/path/to/...-privatekey.p12';
$client_id = '......apps.googleusercontent.com';
$adminEmail = 'admin-account#email.com;
$key = file_get_contents($service_account_pkcs12_file_path);
$auth = new Google_AssertionCredentials($service_account_email, array($group_scope), $key, 'notasecret', 'http://oauth.net/grant_type/jwt/1.0/bearer', $adminEmail);
$client = new Google_Client();
$client->setClientId($client_id); // from API console
$client->setApplicationName("API Project Name");
$client->setUseObjects(true);
$client->setAssertionCredentials($auth);
try {
// Adding or removing from specified list
$sync_status = '';
$service = new Google_DirectoryService($client);
switch ($requested_operation) {
case "add": // Add
$member = new Google_Member(array('email' => $email,
'kind' => 'admin#directory#member',
'role' => 'MEMBER',
'type' => 'USER'));
$service->members->insert($email_list, $member);
break;
case "remove": // Remove
// Users must be removed by ID not by email address
// This is slow and should be changed when
// Google fixes the bug and allows delete by email.
// Get a list of email addresses in the list
$results = $service->members->listMembers($email_list);
// Push results into an array
$arrResults = get_object_vars($results);
// Recursive iterator
$arrIt = new RecursiveIteratorIterator(new RecursiveArrayIterator($arrResults));
// Cycle through the array searching for the email address
foreach ($arrIt as $sub) {
$subArray = $arrIt->getSubIterator();
if ($subArray['email'] === $email) {
// Store an array of the details associated
// with the email address
$outputArray[] = iterator_to_array($subArray);
}
}
// Delete by id
$service->members->delete($email_list, $outputArray[0]['id']);
break;
}
}
catch (Google_ServiceException $e) {
// $e->getCode()
// $e->getMessage()
}
catch (Google_Exception $e) {
// $e->getCode()
// $e->getMessage()
}
catch (Zend_Gdata_Gapps_ServiceException $e) {
// $e->getCode()
// $e->getMessage()
}
}