I wanted to create a stored procedure in SQL Server to complete a POST request. The request would take two parameters.
Curl that I've used for Postman:
curl -X 'POST' \
'https://link' \
-H 'accept: application/json' \
-H 'Authorization: Bearer somepassword' \
-H 'Content-Type: application/json' \
-d '{
"userName": "username",
"password": "password"
}'
I've tried writing the code below, but it doesn't seem to work...
DECLARE #token INT;
DECLARE #ret INT;
DECLARE #url NVARCHAR(MAX);
DECLARE #apiKey NVARCHAR(32);
DECLARE #json AS TABLE(Json_Table NVARCHAR(MAX))
DECLARE #userName varchar(max)
DECLARE #password varchar(max)
DECLARE #body varchar(max)
SET #url = 'https://link'
SET #userName = 'username'
SET #password = 'password'
SET #body = '
{
"userName": "'+#username+'",
"password": "'+#password+'"
}
'
EXEC #ret = sp_OACreate 'MSXML2.XMLHTTP', #token OUT;
IF #ret <> 0
RAISERROR('Unable to open HTTP connection.', 10, 1);
-- This calls the necessary methods.
EXEC #ret = sp_OAMethod #token, 'open', NULL, 'GET', #url, 'false';
EXEC #ret = sp_OAMethod #token, 'send', null, #body
-- Grab the responseText property, and insert the JSON string into a table temporarily. This is very important, if you don't do this step you'll run into problems.
INSERT INTO #json (Json_Table)
EXEC sp_OAGetProperty #token, 'responseText'
-- This is all I have to add to insert into a non-existing table.
SELECT *
FROM OPENJSON((SELECT * FROM #json))
I recommend against using the legacy, hard-to-use OA procedures. Instead, this is a task for a .NET library via SQLCLR. For years I have used this library to handle API calls from the database.
Related
i need to query database in an azure pipeline to find out when was the last login to an environment and if it is more than 2 weeks destroy the environment. to do that i used the below task. but i dont know how can i store the variable to use in the next task. can someone please help me?
- task: SqlAzureDacpacDeployment#1
inputs:
azureSubscription: ' A Service Connection'
AuthenticationType: 'servicePrincipal'
ServerName: 'myserver.database.windows.net'
DatabaseName: 'mydb'
deployType: 'InlineSqlTask'
SqlInline: |
DECLARE #LastLoginDate AS NVARCHAR(50)
SELECT #LastLoginDate = [LastLoginDate]
FROM [dbo].[AspNetUsers]
WHERE UserName <> 'system'
PRINT #LAstLoginDate
IpDetectionMethod: 'AutoDetect'
SQLInlineTask meant for execution of SQL Script on database.
Setting Variables in Pipeline Tasks available with either Bash or PowerShell.
PowerShell Script Task
$query = "DECLARE #LastLoginDate AS NVARCHAR(50)
SELECT #LastLoginDate = [LastLoginDate]
FROM [dbo].[AspNetUsers]
WHERE UserName <> 'system'
PRINT #LAstLoginDate"
# If ARM Connection used with service connection, ignore getting access token
$clientid = "<client id>" # Store in Variable Groups
$tenantid = "<tenant id>" # Store in Variable Groups
$secret = "<client secret>" # Store in Variable Groups
$request = Invoke-RestMethod -Method POST -Uri "https://login.microsoftonline.com/$tenantid/oauth2/token"
-Body #{ resource="https://database.windows.net/"; grant_type="client_credentials"; client_id=$clientid; client_secret=$secret }
-ContentType "application/x-www-form-urlencoded"
$access_token = $request.access_token
# If ARM connection used with service connection, ignore AccessToken Parameter
$sqlOutput = Invoke-Sqlcmd -ServerInstance $.database.windows.net -Database db$ -AccessToken $access_token -query $query
Write-Host "##vso[task.setvariable variable=<variable name>;]$sqlOutput"
Bash
echo "##vso[task.setvariable variable=<variable name>;isOutput=true]<variable value>"
Within same job and different tasks, access it using $(<variable name>)
In Different job, access it using $[ dependencies.<firstjob name>.outputs['mystep.<variable name>'] ]
References:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/set-variables-scripts?view=azure-devops&tabs=bash
https://medium.com/microsoftazure/how-to-pass-variables-in-azure-pipelines-yaml-tasks-5c81c5d31763
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$LoginDate=(Sqlcmd myserver -U $(Username) -P $(Password) -d mydatabase -q "SET NOCOUNT ON; SELECT LastLoginDate=min(LastLoginDate) FROM mytable WHERE UserName<>'system';")
$Last=$LoginDate[2].trimstart()
Write-host $Last
Write-host "##vso[task.setvariable variable=LastLoginDate]$Last"
I'm trying to trigger "play" -funtion with spotify API and tcl/http.
Here is the concept, in curl: https://developer.spotify.com/console/put-play/
curl -X "PUT" "https://api.spotify.com/v1/me/player/play" --data "{\"context_uri\":\"spotify:album:5ht7ItJgpBH7W6vJ5BqpPr\",\"offset\":{\"position\":5},\"position_ms\":0}" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer "
Here's a working example with tcl using exec curl:
set url https://api.spotify.com/v1/me/player/play?device_id=$device_id
set data "{\"context_uri\":\"spotify:album:5ht7ItJgpBH7W6vJ5BqpPr\",\"offset\":{\"position\":5},\"position_ms\":0}"
if {[catch {
exec curl -X "PUT" "$url" --data $data -H "Accept: application/json" \
-H "Content-Type: application/json" -H "Authorization: Bearer $oauth"
} msg]} then {
puts $msg
}
But i'd like to do it with tcl/http, if it's possible.
Here is my best shot so far doing this with http, but it says "malformed json".
if {$incoming == ".play"} {
::http::register https 443 {::tls::socket -autoservername 1}
::http::config -urlencoding utf-8 -useragent {JSON curl/7.55. 1}
set spot_url [http::geturl https://api.spotify.com/v1/me/player/play? \
-method PUT \
-query {{device_id:"d70b1f06*MASKED*36c308",
"context_uri":"spotify:album:5ht7ItJgpBH7W6vJ5BqpPr","offset":{"position":5},"position_ms":0}} \
-headers [list Accept application/json Content-Type application/json Authorization "Bearer $::access_token"]]
set spot_temp [::http::data $spot_url]
::http::cleanup $spot_temp
::http::cleanup $spot_url
return $spot_temp
}
Any idea how to send it correct to avoid malformed json? :D
Thanks!
I'm trying to make a simple proc in TCL that gets data from SPOTIFY API about what track I'm currently playing.
Any ideas are welcome. :D
Format:
GET https://api.spotify.com/v1/me/player/currently-playing
I need to send this:
curl -X "GET" "https://api.spotify.com/v1/me/player/currently-playing?market=ES&additional_types=episode" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer BQAai*****8n-5zXrLypj********hsgafd"
(id code for auth masked)
Reference: https://developer.spotify.com/documentation/web-api/reference/
This is a variant of Donald's solution using Tcl's built-in http support:
package require http;
package require json;
package require tls
::http::register https 443 ::tls::socket
set spotifyToken "BQAai*****8n-5zXrLypj********hsgafd"
proc spotifyGet {api args} {
global spotifyToken;
set url https://api.spotify.com/v1/$api?[http::formatQuery {*}$args]
dict set hdrs Authorization [list Bearer $spotifyToken]
dict set hdrs Accept "application/json"
set token [http::geturl $url \
-type "application/json" \
-headers $hdrs]
if {[http::status $token] eq "ok"} {
set responseBody [http::data $token]
} else {
error "Spotify call failed: [http::error $token]"
}
http::cleanup $token
return [json::json2dict $responseBody]
}
set data [spotifyGet me/player/currently-playing market ES additional_types episode]
Not so complicated, after all, but requires an additional dependency: TclTLS.
As a first cut, here's a very simple wrapper:
proc curl args {
# The options skip showing stuff you don't want in scripted form
# They also enable following redirects; you probably want to do that!
exec curl -s -S -L {*}$args
}
# Usually easiest to keep this sort of thing separate
set spotifyToken "BQAai*****8n-5zXrLypj********hsgafd"
# -G to force the use of the GET verb
set json [curl -G "https://api.spotify.com/v1/me/player/currently-playing?market=ES&additional_types=episode" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer $spotifyToken"]
We can wrap that further:
package require http; # Standard part of Tcl
package require json; # Part of tcllib
proc spotifyGet {api args} {
global spotifyToken; # Assume variable set as earlier
set url https://api.spotify.com/v1/$api?[http::formatQuery {*}$args]
set options {-H "Accept: application/json" -H "Content-Type: application/json"}
lappend options -H "Authorization: Bearer $spotifyToken"
return [json::json2dict [curl -G $url {*}$options]]
}
set data [spotifyGet me/player/currently-playing market ES additional_types episode]
puts [dict get $data item name]
If you're doing more serious JSON work, consider using the rl_json library. And you'll need to explore the data you get back to understand it. (I can't test; I don't use Spotify.)
I'm looking to add an item to our systems through an API call to the supplier's site on given conditions. We have a replicated database and I want the process to be automated.
The supplier's, surprisingly, require you to login on one address then navigate to another to call the SEND but I don't think that the session is being persisted.
The code below is the SP I'm trying to create, which would allow me to use it for a variety of updates, not just this specific type.
The code I have so far is:
CREATE PROCEDURE [dbo].[CallAPI]
(
#Address nvarchar(MAX)
,#Message nvarchar(MAX)
)
AS
DECLARE #url_login nvarchar(MAX) = 'https://credentials'
DECLARE #Login nvarchar(MAX) = '{"username": "uSeR","password": "pAsS"}'
DECLARE #obj int
DECLARE #hResult int
DECLARE #statusText varchar(1000)
DECLARE #status varchar(1000) = 200
---------------------------------------------------------------------------------------------------
EXEC #hResult = sp_OACreate 'MSXML2.ServerXMLHttp', #obj OUT
---------------------------------------------------------------------------------------------------
--Log in
EXEC #hResult = sp_OAMethod #obj, 'Open', NULL, 'post', #url_login, false
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'Content-Type', 'application/json'
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'api-key', 'APIKey'
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'connection', 'keep - alive'
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'cookie', 'monster'
EXEC #hResult = sp_OAMethod #obj, 'send', NULL, #Login
EXEC sp_OAGetProperty #obj, 'StatusText', #statusText out
EXEC sp_OAGetProperty #obj, 'Status', #status out
IF #status = 200
BEGIN
print 'Successful log-in'
-------------------------------------------------------------------------------------------
--Navigate to required address
EXEC #hResult = sp_OAMethod #obj, 'Open', NULL, 'post', #Address, false
EXEC #hResult = sp_OAMethod #obj, 'setRequestHeader', NULL, 'cookie', 'monster'
EXEC sp_OAGetProperty #obj, 'StatusText', #statusText out
EXEC sp_OAGetProperty #obj, 'Status', #status out
IF #status = 200
BEGIN
-----------------------------------------------------------------------------------
--Post message
print 'Successful navigate'
EXEC #hResult = sp_OAMethod #obj, 'send', NULL, #Message
EXEC sp_OAGetProperty #obj, 'StatusText', #statusText out
EXEC sp_OAGetProperty #obj, 'Status', #status out
IF #status = 200
print 'Successful posting'
END
END
IF #status <> 200
SELECT #status, #statusText
EXEC sp_OADestroy #obj
I am currently experimenting with Azure's new "Easy Tables". I have read that it's completely RESTful and I am fully capable of "GET"ting the data in the tables but somehow, I'm not sure how to insert the data I tried using "POST" but no matter what I put into the "data" part of my curl request, it always says
{"error":"An item to insert was not provided"}
Can someone tell me how the body should look like? I'm really getting desperate here...
My table looks like this:
id | createdAt | updatedAt | version | deleted | orgID
notice that only orgID is a column inserted by me
Thanks in advance!
Here is what a request would look like using curl:
curl -X POST -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{
"id" :"1111",
"orgID" : "1234"
}' "http://<your_site_host>/tables/<tablename>?zumo-api-version=2.0.0"
Hope it helps.
$urlAzure = "https://<your_app>.azurewebsites.net/tables/<your_table>";
$data = array (
'<column1>' => <some_text>,
'<column2>' => <some_text>
);
$options = array(
'http' => array(
'method' => 'POST',
'content' => json_encode( $data ),
'header'=> "Content-Type: application/json\r\n" .
"Accept: application/json\r\n"
)
);
$context = stream_context_create($options);
$result= file_get_contents($urlAzure, false, $context);
if ($result === FALSE) { /* Handle error */ }