Azure Table Service REST API error - azure

I would like to execute inset table entity REST API in Table Storage Service but it doesn't work.
I referred this doc.
My request code is here,
<?php
// storage account name
$account = "mystgaccount";
$tablestoragename = "mytablename";
$accessKey = "myaccesskey";
$date = gmdate('D, d M Y H:i:s T',time());
$api_version = "2015-12-11";
$url = "https://$account.table.core.windows.net/$tablestoragename";
$method = "POST";
$body = '{"Address":"MountainView","Age":23,"AmountDue":200.23,"CustomerCode#odata.type":"Edm.Guid","CustomerCode":"c9da6455-213d-42c9-9a793e9149a57833","CustomerSince#odata.type":"Edm.DateTime","CustomerSince":"2008-0710T00:00:00","IsActive":true,"NumberOfOrders#odata.type":"Edm.Int64","NumberOfOrders":"255","PartitionKey":"mypartitionkey","RowKey":"myrowkey"}';
$stringToSign = [
// VERB
$method,
// Content-MD5
'',
// Content-Type
'',
// Date
$date,
];
$stringToSign = array_merge($stringToSign, ["/$account/$tablestoragename"]);
$stringToSign = implode("\n", $stringToSign);
$signature = base64_encode(hash_hmac('sha256', $stringToSign, base64_decode($accessKey), true));
$headers = [
"x-ms-date:{$date}",
"x-ms-version:$api_version",
"Authorization:SharedKey $account:{$signature}",
"Content-Type: application/json",
];
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_POSTFIELDS => http_build_query($body),
);
curl_setopt_array($ch, $proxy_options);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
var_dump($response);
echo curl_error($ch);
curl_close($ch);
?>
Response
"<?xml version="1.0" encoding="utf-8"?><m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"><m:code>AuthenticationFailed</m:code><m:message xml:lang="en-US">Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:b93fe560-0002-0028-129a-571361000000
Time:2017-11-07T07:34:13.3303714Z</m:message></m:error>"
I read related questions but it hasn't resolved yet :(
Do you have any ideas?

One possible reason for this error could be because of Content-Type header. You're specifying this header in your request but is not included in your $stringToSign. Please try again by changing your $stringToSign to something like:
$stringToSign = [
// VERB
$method,
// Content-MD5
'',
// Content-Type
'application/json',
// Date
$date,
];

Related

simplest possible XML-RPC query example using powershell?

Looking to simplify or even "dumb down" this example:
$source = #'
namespace OpenSubtitlesAPI
{
using CookComputing.XmlRpc;
[XmlRpcUrl("http://api.opensubtitles.org/xml-rpc")]
public interface IOpenSubtitles : IXmlRpcProxy
{
[XmlRpcMethod("LogIn")]
XmlRpcStruct LogIn(string username, string password, string language, string useragent);
[XmlRpcMethod("LogOut")]
XmlRpcStruct LogOut(string token);
[XmlRpcMethod("SearchSubtitles")]
XmlRpcStruct SearchSubtitles(string token, XmlRpcStruct[] queries);
[XmlRpcMethod("SearchSubtitles")]
XmlRpcStruct SearchSubtitles(string token, XmlRpcStruct[] queries, int limit);
}
public class ProxyFactory
{
public static IOpenSubtitles CreateProxy()
{
return XmlRpcProxyGen.Create<IOpenSubtitles>();
}
}
}
'#
so that the simplest possible xml-rpc query is invoked. Using .NET Core on Linux.
also trying:
desired output:
$VAR1 = {
'description' => 'Mountain Dew',
'upc' => '012000000850',
'upce' => '01208500',
'issuerCountryCode' => 'us',
'noCacheAfterUTC' => bless( do{\(my $o = '2020-11-16T17:20:29')}, 'Frontier::RPC2::DateTime::ISO8601' ),
'pendingUpdates' => '0',
'issuerCountry' => 'United States',
'ean' => '0012000000850',
'size' => '12fl oz (355mL)',
'found' => bless( do{\(my $o = '1')}, 'Frontier::RPC2::Boolean' ),
'status' => 'success',
'message' => 'Database entry found',
'lastModifiedUTC' => bless( do{\(my $o = '2014-05-27T04:52:02')}, 'Frontier::RPC2::DateTime::ISO8601' )
};
Adapting from an example script in perl:
#!/usr/bin/perl
#
# Get an RPC key assigned on the "Account Info" page on https://www.upcdatabase.com/
# Then substitute your own RPC key for $key below.
#
# Usage examples:
# perl_example_new.pl test
# perl_example_new.pl help
# perl_example_new.pl lookup upc 012000000850
# perl_example_new.pl lookup ean 0012000000850
use Frontier::Client;
use Data::Dumper;
use strict;
my $server_name = 'www.upcdatabase.com';
my $key = '445d...aa3';
my $server = Frontier::Client->new( 'url' => 'https://' . $server_name . '/xmlrpc', debug => 0, );
my $method = shift;
my $result = $server->call($method, { rpc_key => $key, #ARGV } );
print Dumper($result);
__END__
adapting to powershell using the REPL console:
PS /home/nicholas/powershell>
PS /home/nicholas/powershell> Get-Help Send-XmlRpcRequest -Examples
NAME
Send-XmlRpcRequest
SYNOPSIS
Send a XML RPC Request
-------------------------- EXAMPLE 1 --------------------------
PS > Send-XmlRpcRequest -Url "example.com" -MethodName "updateName" -Params #('oldName', 'newName')
---------
Description
Calls a method "updateName("oldName", "newName")" on the server example.com
PS /home/nicholas/powershell>
PS /home/nicholas/powershell> Send-XmlRpcRequest -Url "www.upcdatabase.com" -MethodName "012000000850" -Params #('fjkdlsfjd')
Exception: /home/nicholas/.local/share/powershell/Modules/XmlRpc/1.0.1.1/XmlRpc.psm1:323
Line |
323 | $doc.LoadXml($response)
| ~~~~~~~~~~~~~~~~~~~~~~~
| Exception calling "LoadXml" with "1" argument(s): "Root element is missing."
PS /home/nicholas/powershell>
or using a script file.

Azure table storage REST Query doesn't show new entries

I'm building a query for a Azure Storage Account(tables in this case). I try to receive the last log entries of the last day.
The filter looks like this in the storage query builder:
{
"filter": [
{
"id": "{ID}",
"andOr": "And",
"field": "TIMESTAMP",
"type": "DateTime",
"operator": ">=",
"value": "datetime'2019-11-18T10:08:41.296Z'",
"timeValue": "Last 24 hours",
"timestampType": "time",
"customTimestamp": {
"lastNumber": 7,
"lastTimeUnit": "Days"
},
"isLocal": true
}
],
"select": null,
"group": {
"id": "{ID}",
"children": [
"{CHILD}"
]
},
"top": null,
"filterType": "Query Builder",
"fileVersion": 0.2
}
This query returnes all the entries from the last day.
I tried to use this filter in the Azure REST API call. in a powershell function like this:
function GetTableEntityAll($TableName) {
$version = "2017-04-17"
$resource = "$tableName()"
$DST = [DateTime]::Today.AddDays(-1)
$table_url = "https://$storageAccount.table.core.windows.net/$resource"+ '?$filter=Timestamp gt datetime' + "'"+ $DST.ToString("s") + "'"
write-host $table_url
$GMTTime = (Get-Date).ToUniversalTime().toString('R')
$stringToSign = "$GMTTime`n/$storageAccount/$resource"
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Convert]::FromBase64String($accesskey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
$signature = [Convert]::ToBase64String($signature)
$headers = #{
'x-ms-date' = $GMTTime
Authorization = "SharedKeyLite " + $storageAccount + ":" + $signature
"x-ms-version" = $version
Accept = "application/json;odata=fullmetadata"
}
$item = Invoke-RestMethod -Method GET -Uri $table_url -Headers $headers -ContentType application/json
return $item.value
}
The URL I generate with this is:
https://{Accountname}.table.core.windows.net/{Tablename}()?$filter=Timestamp gt datetime'2019-11-18T00:00:00'
This doesn't return any records. I also tried to encode the url but that doesns't work either. If I change the datetime to 2016 I receive the first few records.
Azure documentation: https://learn.microsoft.com/en-us/rest/api/storageservices/querying-tables-and-entities
Any ideas?

How to update session entity in Dialogflow?

I have defined an entity named visible_objects in my Dialogflow agent.
In the Dialogflow console I have put one entry named placeholder2 with a synonym placeholder.
When a user starts interacting with the agent, I'm updating this entity via the projects.agent.sessions.entity patch request. Following is the content of the request I'm sending.
`{
"name": "projects\/{PROJECT_NAME}\/agent\/sessions\/{SESSION}\/entityTypes\/visible_objects",
"entityOverrideMode": "ENTITY_OVERRIDE_MODE_OVERRIDE",
"entities": [
{
"value": "door",
"synonyms": [
"door"
]
},
{
"value": "desk",
"synonyms": [
"desk"
]
},
{
"value": "test tubes",
"synonyms": [
"test tubes",
"test",
"tubes"
]
}
]
}`
And this is the code I'm using to generate it:
<?php
$json = file_get_contents('php://input');
$request = json_decode($json, true);
$df_action = $request['queryResult']['action'];
$df_contexts = $request['queryResult']['outputContexts'];
$df_parameters = $request['queryResult']['parameters'];
// taken from private_key in my GCP authentication .json file
$CLIENT_ACCESS_TOKEN = "-----BEGIN PRIVATE KEY-----xxxxxxxxxxxxxx---END PRIVATE KEY-----\n";
// loop through the visible objects and prepare the output for dialogflow
foreach($_SESSION['STORY']['VISIBLE_OBJECTS'] as $visible_object)
{
unset($synonyms); // clear any existing synonyms
$synonyms = array();
$synonyms[] = $visible_object['name'];
if (strpos($visible_object['name'], ' ', 1))
{ // multiple words so split it as synonyms
$sub_objects = explode(' ', $visible_object['name']);
foreach($sub_objects as $sub_object)
$synonyms[] = $sub_object;
}
// add the object to the user entity
$user_ent_objects[] = array('value'=>$visible_object['name'], 'synonyms'=>$synonyms);
}
// prepare user_entity
$user_entity = array('name'=>$request['session'] . '/entityTypes/visible_objects', 'entityOverrideMode'=>'ENTITY_OVERRIDE_MODE_OVERRIDE', 'entities'=>$user_ent_objects);
// log for debugging
file_put_contents($SITE_DIR . '/webhook/user-entity-visible-objects.txt', json_encode($user_entity,JSON_PRETTY_PRINT));
$ch = curl_init('https://dialogflow.googleapis.com/v2/' . $request['session'] . '/entityTypes/visible_objects');
curl_setopt($ch, CURLOPT_POST, true); // tell it we're posting
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer ' . $CLIENT_ACCESS_TOKEN)); // set the headers
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($user_entity)); // load our data
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$curl_response = curl_exec($ch); // execute it
?>
I have an intent which is "look on the object name", where object name is mapped to the visible_objects entity. Here's what I'm seeing for some example phrases:
look on the placeholder -> "placeholder" is detected as object name
look on the test -> no object name detected
look on the tubes -> no object name detected
look on the desk -> no object name detected
Based on these responses is appears the session entity is not being updated as the new values are not detected and similarly the old value placeholder2 is not overwritten.
My webhook is written in PHP, and I'm not using the Google SDK (it is only in alpha for PHP). I am capturing the response from the request curl_exec but nothing is being returned.
Using curl_getinfo I'm seeing the following:
`[url] => https://dialogflow.googleapis.com/v2/projects/escaperoom-447aa/agent/sessions/SESSION_ID_MASKED/entityTypes/visible_objects
[content_type] => text/html; charset=UTF-8
[http_code] => 400
[header_size] => 144
[request_size] => 2002
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.072034
[namelookup_time] => 0.023728
[connect_time] => 0.031063
[pretransfer_time] => 0.065598
[size_upload] => 394
[size_download] => 0
[speed_download] => 0
[speed_upload] => 5472
[download_content_length] => 1555
[upload_content_length] => 394
[starttransfer_time] => 0.065659
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => 216.58.192.234
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => 66.198.240.46
[local_port] => 41442
`
Can anyone see what I'm doing wrong here?
The issue is that you're not setting $CLIENT_ACCESS_TOKEN to an access token. You're setting it to your private key which should be associated with a service account.
You will need to use that private key to generate an access token - it is not the access token itself. Since there is a service definition for the Dialogflow service, you can choose to just generate a signed JWT for the service.

TFS Code Search/Work Rest API return 404

we are using TFS on-premise.
TFS version:
Microsoft Visual Studio Team Foundation Server
Version 16.122.27409.2 (2018).
We need to perform TFS source control (Code Search)
According to MS API documentation this the way to use TFS REST API.
Build and Release API are working, but search API return 404.
Search Code extension installed and working fine from TFS portal.
API Url:
POST: http://{DNS}:8080/tfs/{Collection}/{Project}/_apis/search/codesearchresults?api-version=4.1-preview.1
the result:
Please help, what I'm, doing wrong?
You can't just open it in a browser. You have to provide a request body, as expressed clearly in the API examples:
{
"searchText": "CodeSearchController",
"$skip": 0,
"$top": 1,
"filters": {
"Project": [
"MyFirstProject"
],
"Repository": [
"MyFirstProject"
],
"Path": [
"/"
],
"Branch": [
"master"
],
"CodeElement": [
"def",
"class"
]
},
"$orderBy": [
{
"field": "filename",
"sortOrder": "ASC"
}
],
"includeFacets": true
}
Just as Daniel said "You can't just open it in a browser. You have to provide a request body"
So you can use tools such as Postman to send the request with request body, or you can use PowerShell to call the REST API with request body.
Besides, based on my test it seems the REST API you mentioned (Code Search Results) is not apply to on-premise TFS. I tested on TFS 2018 Update2 (Version 16.131.27701.1), it always return "count": 0,.
However you can use below REST API to search code:
POST http://server:8080/tfs/DefaultCollection/{Project}/_api/_search/postCodeQuery?api-version=4.1-preview.1
Request Body:
{"searchText":"<test1>",
"scope":"Team Foundation Server",
"filters":"{\"ProjectFilters\":[\"0511ScrumTFVC\"]}",
"skipResults":0,
"takeResults":50,
"sortOptions":""
}
Below PowerShell sample for your reference:
Param(
[string]$baseurl = "http://server:8080/tfs/DefaultCollection",
[string]$projectName = "ProjectName",
[string]$user = "username",
[string]$token = "password"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
function CreateJsonBody
{
$value = #"
{"searchText":"<test1>",
"scope":"Team Foundation Server",
"filters":"{\"ProjectFilters\":[\"ProjectName\"]}",
"skipResults":0,
"takeResults":50,
"sortOptions":""
}
"#
return $value
}
$json = CreateJsonBody
$uri = "$baseurl/$($projectName)/_api/_search/postCodeQuery?api-version=4.1-preview.1"
Write-Host $uri
$result = Invoke-RestMethod -Uri $uri -Method POST -Body $json -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$result = $result | convertto-json
Write-host $result

Custom Document Fields

I'm using the dev account and the demo.docusign.net site to test out the API. I want to create a template with a document that has custom data fields. I created a template and on the page where you drag fields on to the document, I created a custom field. I called it "Last Name". I saved the custom field and saved the template. Now I want to create a new document for signing through the API and populate that field. Using the Walkthroughs as a guide, I was able to create a new draft envelope from a template. I then wanted to populate the custom field with data. However, this is failing. I'm getting the following error:
{
"errorCode": "INVALID_REQUEST_BODY",
"message": "The request body is missing or improperly formatted."
}'
Below is my code based off the Walkthroughs. In addition to having a custom field attached at design time, I wanted to test dynamically adding a new custom field and modifying it as well. So, first I make a POST request to add a new field and set it using the Recipients/Tabs API. Then I make a GET request to get the Tabs for the recipient so I can capture the Tag ID. Then I make a PUT request to modify the field and that's where I get the error message. But the request body looks fine to me and it contains the only required field for TagId. I assume the only other needed field is one to set the value. The same request body works fine for the POST request. I just copied it and changed the fields. The POST works fine and I can validate the added field by opening it in the Console. The new field is there. It's just the PUT to modify that isn't working.
/////////////////////////////////////////////////////////////////////////////////////////////////
// STEP 1 - Add New Tab
/////////////////////////////////////////////////////////////////////////////////////////////////
$curl = curl_init($baseUrl . "/envelopes/" . $envelopeId . "/recipients/1/tabs" );
$data = array (
'textTabs' =>
array (
0 =>
array (
'documentId' => '1',
'pageNumber' => '1',
'tabLabel' => 'test tab',
'value' => 'test',
),
),
);
$data_string = json_encode($data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string),
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 201 ) {
echo "error calling webservice, status is:" . $status;
exit(-1);
}
$response = json_decode($json_response, true);
curl_close($curl);
//--- display results
/////////////////////////////////////////////////////////////////////////////////////////////////
// STEP 2 - Get recipient tab information
/////////////////////////////////////////////////////////////////////////////////////////////////
$curl = curl_init($baseUrl . "/envelopes/" . $envelopeId . "/recipients/1/tabs" );
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 200 ) {
echo "error calling webservice, status is:" . $status;
exit(-1);
}
$response = json_decode($json_response, true);
curl_close($curl);
$lastNameTabID = $response['textTabs'][0]['tabId'];
$testTabID = $response['textTabs'][1]['tabId'];
//--- display results
/////////////////////////////////////////////////////////////////////////////////////////////////
// STEP 3 - update tab value
/////////////////////////////////////////////////////////////////////////////////////////////////
$curl = curl_init($baseUrl . "/envelopes/" . $envelopeId . "/recipients/1/tabs" );
$data = array (
'textTabs' =>
array (
0 =>
array (
'tabId' => $testTabID,
'value' => 'Some Value',
),
),
);
$data_string = json_encode($data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_PUT, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data_string),
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 201 ) {
echo "error calling webservice, status is:" . $status;
exit(-1);
}
$response = json_decode($json_response, true);
curl_close($curl);
And here is the output of the Request Body
data_string= '{"textTabs":[{"tabId":"627883d0-542c-40c7-a58c-ce68d9e057e1","value":"Some Value"}]}'
I appreciate some guidance.
Thanks
Joe
I think this is easier than we think. You should be able to define the additional tag in the post to create the envelope. Below is part of my json to define a template role and text tabs. The first one is a field defined in the Template labeled "Company". The second one is a data field I'm adding on the fly and placing on the 3rd page with XY coordinates. You can also place this using anchor text.
"templateRoles": [
{
"tabs": {
"textTabs": [
{
"tabLabel": "Company",
"value": "Acme Inc"
},
{
"tabLabel": "business",
"value": "widgets",
"pageNumber": "3",
"documentId": "1",
"yPosition": "300",
"xPosition": "300",
"locked": false
}
]
},
"roleName": "Customer",
"name": "Customer Bob",
"email": "signerrob#outlook.com"
}
],
Alright, so I did a little digging and think I have what we need here. First, to get the Recipient ID as well as associated Tab ID's for the envelope, use the following GET: v2/accounts/:accountId/envelopes/:envelopeId/recipients. This will give you what you need to edit existing tags. Once you have the info here, you can use the PUT v2/accounts/:accountId/envelopes/:envelopeId/recipients/:recipientId/tabs to edit the tabs you're looking to edit. Here is a sample JSON request I sent using Postman to successfully update a text tabs value.
{
"textTabs": [
{
"tabId": "c75d32c4-8024-48c0-975a-acc232b20212",
"value": "ABC Corp",
}
]
}
To add tabs to that recipient, use the same URL as the edit, but use a POST.

Resources