How to use the Content-Length HTTP header in PHP? - http

I am trying to include the Content-Length HTTP header in a call and I am struggling to get the length of the XML request string. I have sent a request with the API explorer which returned Content-Length in its response headers.
So I copied the XML and attempted to get the length from it with code as I know the length is 575, but the best I can do is return the length as 567. The code I used is below, if anyone can point me in the correct direction I will be very grateful.
$testXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<GetFeedbackResponse
xmlns=\"urn:ebay:apis:eBLBaseComponents\">
<Timestamp>2017-08-08T19:52:42.536Z</Timestamp>
<Ack>Failure</Ack>
<Errors>
<ShortMessage>User not found.</ShortMessage>
<LongMessage>The user "XXXXX" was not found in our database.</LongMessage>
<ErrorCode>21</ErrorCode>
<SeverityCode>Error</SeverityCode>
<ErrorParameters ParamID=\"0\">
<Value>XXXXX</Value>
</ErrorParameters>
<ErrorClassification>RequestError</ErrorClassification>
</Errors>
<Version>989</Version>
<Build>E989_INTL_API_18131002_R1</Build>
</GetFeedbackResponse>";
//length is 575 according to eBay
$testXml = new \SimpleXMLElement($testXml);
$testXml = $testXml->asXML();
$testXml = str_replace(" ", "", $testXml);
echo strlen($testXml);
//echos length 567

Related

how to get partial data from url ,these code is giving me failed to decode error python3.0

can anyone help me how to get partial data from url ,these code is giving me failed to decode error
import requests
url = "http://tools.ietf.org/rfc/rfc2822.txt"
start=24
end=30
headers = {"Range":f"bytes={start}-{end}"}
r = requests.get(url,stream=True,headers=headers)
print(r.text)
You ask for a range of the resource, which the server reponds with, but due to the standard header Accept-Encoding: "gzip, deflate", the server sends the bytes back of the encoded resource. In order to retrieve the non-encoded bytes use the following header:
import requests
url = "http://tools.ietf.org/rfc/rfc2822.txt"
start=24
end=30
headers = {"Range":f"bytes={start}-{end}", "Accept-Encoding": None}
r = requests.get(url,stream=True,headers=headers)
print(r.text)

Send a POST request in R package

I've been trying to use httr package in R to send a POST request
The website which I'm trying to send a POST request states to do the following:
POST /newwebservices/locationverifier.asmx/findLocation2 HTTP/1.1
Host: citizenatlas.dc.gov
Content-Type: application/x-www-form-urlencoded
Content-Length: length
str=string&f=string
where str takes an address in Washington DC such as "701 FARADAY PL NE, WASHINGTON, DC 20017" and f takes the format requested in this case I want "json"
I tried :
url = "/newwebservices/locationverifier.asmx HTTP/1.1"
body = list(
"Host" = "citizenatlas.dc.gov",
"Content-Type" = "application/x-www-form-urlencoded",
"Content-Length" = length,
"str"="3513 S St NW",
"f"="json"
)
httr::POST(url,body, verbose)
I also tried Get
This is what they state to put in
GET /newwebservices/locationverifier.asmx/findLocation2? str=string&f=string HTTP/1.1
Host: citizenatlas.dc.gov
or
GET("http://citizenatlas.dc.gov/newwebservices/locationverifier.asmx/findLocation2?str=3513 S St NW&f=json")
but nothing is working. By the way, I had no problem making the request using Mathematica.
I will appreciate any help. Thank You in Advance.
There are a few different things going on here. Below works:
url <- "http://citizenatlas.dc.gov/newwebservices/locationverifier.asmx/findLocation2"
body <- list(str = "3513 S St NW", f = "json")
httr::POST(url, body = body, encode = "json")
A few differences:
POST is to host + endpoint, not just endpoint
Details on response (content type, length) are not included
Encoding specified for body (per httr::POST documentation)
body and encode are named because they aren't in positions from documentation, so positional argument matching won't work

How to send HTTP SOAP request to local Sonos device with NodeMCU?

How do I send a simple HTTP POST/GET SOAP request to my Sonos loudspeaker in Lua?
I have tried simple HTTP POST and GET requests with success, but I do not know where to start with SOAP requests.
Note: I am a newbie at this. I have never worked with a NodeMCU before nor have I programmed in Lua. I have experience in other languages though.
I know how to do it in C#, Java and PHP.
This works in Postman:
HTTP Headers:
SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause
Content-Type:text/xml; charset="utf-8"
Host:192.168.0.10:1400
BODY:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Pause xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:Pause></s:Body></s:Envelope>
What I did is this and it does not work:
sendRequest("192.168.0.10")
function sendRequest(url)
print("Sending request to Sonos Playbar...")
sk = net.createConnection(net.TCP, 0)
sk:on("receive", function(sck, c) print(c) end )
sk:on("connection", function(sck, c)
print("\r\n\r\n\r\n")
-- HTTP 405: Method not allowed
-- sck:send("POST / HTTP/1.1\r\nHost: "..url..":1400\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
-- HTTP 500, UPnP 402: Invalid arguments
-- sck:send("POST /MediaRenderer/AVTransport/Control HTTP/1.1\r\nHost: "..url..":1400\r\nSOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\nConnection: keep-alive\r\n\r\nAccept: */*\r\n\r\n")
local content = nil;
content = "POST /MediaRenderer/AVTransport/Control\r\n"
content = content.."Host:192.168.0.10:1400\r\n"
content = content.."Content-Type:text/xml; charset=utf-8\r\n"
content = content.."SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n"
content = content.."\r\n"
-- SOAP Body
content = content.."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
content = content.." s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
content = content.."<s:Body>"
content = content.."<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">"
content = content.."<InstanceID>0</InstanceID>"
content = content.."</u:Pause>"
content = content.."</s:Body>"
content = content.."</s:Envelope>"
-- SOAP Body End
print(content.."\r\n\r\n\r\n")
sck:send(content);
end)
sk:connect(1400, url)
end
I am getting this response of my Sonos player:
HTTP/1.1 500 Internal Server Error
CONTENT-LENGTH: 347
CONTENT-TYPE: text/xml; charset="utf-8"
EXT:
Server: Linux UPnP/1.0 Sonos/34.16-37101 (ZPS9)
Connection: close
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring>UPnPError</faultstring>
<detail>
<UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
<errorCode>401</errorCode>
</UPnPError>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
What am I doing wrong? I copied and paste the text, basically. Maybe it is the order of headers? Maybe I am declaring the headers wrong or something?
I don't have a Sonos device to play with. Thus, this ain't a confirmed answer.
The string in your content variable is not a valid HTTP request. Sonos doesn't understand it as the error code 401 means "invalid action".
You need the separate HTTP headers with \r\n. An extra \r\n needs to be placed right before the HTTP body. Therefore, I'd expect that your content should be:
"POST http://192.168.0.10:1400/MediaRenderer/AVTransport/Control\r\n
SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n
Content-Type:text/xml; charset=\"utf-8\"\r\n
Host:192.168.0.10:1400\r\n\r\n
<s:Envelope xmlns:s=\"http://schemas.xml......"
Finally! I have it working! Below is the code to get it working:
sendRequest("192.168.0.10")
function sendRequest(url)
print("Sending request to Sonos Playbar...")
local content = nil;
content = "";
-- SOAP Body
content = content.."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
content = content.." s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
content = content.."<s:Body>"
content = content.."<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">"
content = content.."<InstanceID>0</InstanceID>"
content = content.."</u:Pause>"
content = content.."</s:Body>"
content = content.."</s:Envelope>"
-- SOAP Body End
http.post("http://"..url..":1400/MediaRenderer/AVTransport/Control",
'Content-Type: text/xml; charset="utf-8"\r\n'..
'Host:'..url..':1400\r\n'..
'SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n',
content, function(code, data)
if(code < 0) then
print("HTTP request failed with code "..code)
else
print(code, data)
end
end)
end

Not getting Range header

I am trying to resume an upload from google drive, I have the id of the file when I close the connection I make this session after the Internet is connected again:
var request = (HttpWebRequest)WebRequest.Create(fileUri);
request.Method = "PUT";
request.ContentLength = 0;
request.Headers.Add("Content-Range", "bytes */" + FileByteArray.Length);
try
{
var response = request.GetResponse();
}
catch (WebException e)
{
fileRange = e.Response.Headers.Get("Range");
}
}
I am not getting the Range header, why is that?
Content-Range indicates which range of the original entity is contained in the body of either a request (like your PUT request) or a 206 partial response. Range is set by the client not the server in order to request a sub-range. I would assume that the server you are talking to will not respond with the uploaded chunk, so a Content-Range (and Range in no case) will not be present as a response header.
In your code snippet the actual upload range is missing for Content-Range (see the updated HTTP RFC). It has to have the form of:
Content-Range: bytes 42-1233/1234
which means: upload byte 42-1233 of an entity whose total size is 1234 byte.
Or when the complete length is unknown:
Content-Range: bytes 42-1233/*
So remove the check for the Range header and specify the complete upload range and you should be fine.

How do I inject new request header with json data in proxy request flow?

I am trying to inject a new request header in the proxy request flow using JS policy to be sent to the backend server. When I look at the debug trace, I see that the json data in the request header is distorted.
I am trying to inject some string like
{"scope":"","time_till":2264,"id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM","custom_data":{"c_id":"test_data"}}
But when I look at the trace window I see this
{"scope":"","time_till":2264,id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM,"custom_data":{"c_id":"test_data"}}
what am I doing wrong?
var obj = {"scope":"","time_till":2264,"id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM","custom_data":{"c_id":"test_data"}};
var header_str = JSON.stringify(obj);
context.setVariable('json-header',header_str);
request.headers['x-json-hedar']= header_str;
I tested your code and it seems to work. Here's an example response where I set the header string as a response:
HTTP/1.1 200 OK
User-Agent: curl/7.30.0
Accept: */*
x-json-header: {"scope":"","time_till":2264,"id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM","custom_data":{"c_id":"test_data"}}
Content-Length: 0
It appears this is only an issue with the Apigee debug session / trace tool as the header value was set correctly. Here was the JSON download of the debug session showing this header value:
{
"name": "x-json-header",
"value": "{\"scope\":\"\",\"time_till\":2264,id_1\":\"hUXLXVqpA1J4vA9sayk2UttWNdM,\"custom_data\":{\"c_id\":\"test_data\"}}"
}
You can see that the value passed to the UI for displaying the debug info has the malformed json:
id_1\":\"hUXLXVqpA1J4vA9sayk2UttWNdM,
This does not appear to be a problem with the Apigee debug/trace UI. I see the malformed JSON trickle down to my backend service.
Here is the header I'm trying to send -
{"timeStamp":"2349218349381274","latitude":"34.589","longitude":"-37.343","clientIp":"127.0.0.0","deviceId":"MOBILE_TEST_DEVICE_AGAIN","macAddress":"23:45:345:345","deviceType":"phone","deviceOS":"iOS","deviceModel":"iPhone 5S","connection":"5G","carrier":"Vodafone","refererURL":"http://www.google.com","xforwardedFor":"129.0.0.0","sessionId":"kfkls498327ksdjf","application":"mobile-app","appVersion":"7.6.5","serviceVersion":"1.0","userAgent":"Gecko"}
But Apigee reads the header as below. Note the missing start quotes from some fields.
{"timeStamp":"2349218349381274",latitude":"34.589,longitude":"-37.343,clientIp":"127.0.0.0,deviceId":"MOBILE_TEST_DEVICE_AGAIN,macAddress":"23:45:345:345,deviceType":"phone,deviceOS":"iOS,deviceModel":"iPhone 5S,connection":"5G,carrier":"Vodafone,refererURL":"http://www.google.com,xforwardedFor":"129.0.0.0,sessionId":"kfkls498327ksdjf,application":"mobile-app,appVersion":"7.6.5,serviceVersion":"1.0,"userAgent":"Gecko"}
The header is used in a service callout to a backend service which parses it. And rightly so, I get the below error -
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('l' (code 108)): was expecting double-quote to start field name
at [Source: java.io.StringReader#22549cdc; line: 1, column: 35]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1378)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:599)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:520)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleUnusualFieldName(ReaderBasedJsonParser.java:1275)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._parseFieldName(ReaderBasedJsonParser.java:1170)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:611)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:301)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942)
I encounter strange behaviour when adding JSON to a context variable for example like the following:
var header_str = JSON.stringify(obj);
context.setVariable('json-header',header_str);
I appreciate this is an example so you may not have included the full extent of the problem but this normally works (now it is not added to a variable first):
request.headers['x-json-header'] = JSON.stringify(obj);
Code like this also works if you can send the request from JavaScript
var headers = {"Accept": "application/json", "Accept-Language": "en"};
var sessionRequest = new Request(url, 'POST', headers, body);
var exchange = httpClient.send(sessionRequest);
exchange.waitForComplete()
if (exchange.isSuccess()){
var responseObj = exchange.getResponse().content.asJSON;
if (responseObj.error){
request.content += JSON.stringify(responseObj);
}
}
Also, I have had success with using an AssignMessage policy to build a request, followed by a Callout policy to read the stored request and then make that request and store the result in a response object which can then be read by an Extract Variables policy.

Resources