UPnP POST to Printers Data Sink URI - soap

I have some other posts where I've been working with posting data to a UPnP printer. Basically creating a control point from scratch (this is still POC and I'll be implementing across multiple device types so I'm trying to get basic understanding first). So far I'm able to discover the printer, request a print job and get back a data sink url to post the content to be printed. At this point I attempt a POST with simple xhtml data, but the request seems to time out every time with the following exception:
The remote server returned an error: NotFound.
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)
If I hit the url in the browser, I get back HTTP 405 Method Not Allowed
I'm wondering if the server is ignoring the post due to bad data, or I'm missing headers or something along these lines.
I've already gone through the docs on upnp.org for the Printer Basic service, along with SOAP 1.1 UPnP Profile, both of which greatly helped get as far as I have.
does anybody have any thoughts?
Here's a copy of my xhtml:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML-Print 1.0//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-print10.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<title>test</title>
</head>
<body>
<div>hello world</div>
</body>
</html>
I'm using C# to create and send a HttpWebRequest. Here is the code that does that (I have a couple variations, another using WebClient)
private void SendToPrinter(string printUri, string content)
{
var request = WebRequest.Create(new Uri(printUri)) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "text/xml; charset=\"utf-8\"";
request.ContentLength = content.Length;
request.Headers[SoapHeaderName] = CreateJobHeader; // this probably isn't necessary
request.BeginGetRequestStream(ar =>
{
var requestStream = request.EndGetRequestStream(ar);
using (var sw = new StreamWriter(requestStream))
{
sw.Write(content);
sw.Close();
}
request.BeginGetResponse(a =>
{
var response = request.EndGetResponse(a);
var responseStream = response.GetResponseStream();
using (var sr = new StreamReader(responseStream))
{
var results = sr.ReadToEnd();
}
}, null);
}, null);
}
raw post data from fiddler
POST http://10.20.201.90/upnp/print/1d153438-1e90-1f0b-8b54-984be15df0fe HTTP/1.1
Content-Type: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:device:Printer:1#SendDocument"
Host: 10.20.201.90
Content-Length: 482
Expect: 100-continue
<?xml version="1.0" encoding="UTF-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:SendDocument xmlns:u="urn:schemas-upnp-org:device:Printer:1"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>test</title></head><body><div>hello world</div></body></html></u:SendDocument></s:Body></s:Envelope>

One issue that kept me from printing was that the printer was set to ask which tray to print from. This blocked the message from being printed. Here's the final SOAP message. I did not escape it.
<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">
<s:Body>
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head><title>test</title></head>
<body><div>hello world</div></body>
</html>
</s:Body>
</s:Envelope>

Related

Delphi: REST Request with BASIC authentication

I'm using TRESTClient/THTTPBasicAuthenticator/TRESTRequest/TRESTResponse to get data from a server.
With response Ok (200), instead of receiving JSON data, I get as content this:
<script type="text/javascript">
<!-- function redirectToIndex()
{
var adresse = window.location.pathname.split('/');
var httpURL = window.location.hostname + "/" + "app"; // redirect to root
var httpsURL = "https://" + httpURL;
window.location = httpsURL;
}
redirectToIndex(); //-->
This is when TRESTRequest.Accept is empty. If I change for TRESTRequest.Accept:= 'application/json', I get an error
406 - Not Acceptable
Could you tell me what's wrong with my request?
Thank you Peter.
I managed to clarify with the API support the BASIC Authentication using the correct login/password . The documentation was inaccurate.
Access is now working as expected.

Web API Post call from c# client always return with 200 OK

I got a C# client that performs POST call like so:
public void Add(ModelA newObj)
{
HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create("http://www.x.com/api/ModelA");
string json = JsonConvert.SerializeObject(newObj, Formatting.None,
new JsonSerializerSettings {
PreserveReferencesHandling = PreserveReferencesHandling.All
});
var messagebyte = Encoding.ASCII.GetBytes(json);
httpRequest.Method = "POST";
httpRequest.ContentType = "application/json";
httpRequest.ContentLength = messagebyte.Length;
// Send request
using (var stream = httpRequest.GetRequestStream())
{
stream.Write(messagebyte, 0, messagebyte.Length);
stream.Close();
}
// Get response
using (var response = httpRequest.GetResponse() as HttpWebResponse)
{
response.Close();
}
}
And the controller looks like that:
[ResponseType(typeof(ModelA))]
public IHttpActionResult PostModelA(ModelA newModelA)
{
return NotFound();
}
And surprisingly, the client response is 200 OK. Moreover, the property of "response.Method" is "GET" instead of "POST". What am I missing here ?
Ok, so apparently my web host changed some configuration and the API calls should have been made to http://x.com instead of http://www.x.com.
I found it out since I tried to perform POST call using the service of https://www.hurl.it/, and the call returned something like that:
HEADERS
Content-Length: 163
Content-Type: text/html; charset=UTF-8
Date: Mon, 29 Dec 2014 04:40:55 GMT
Location: http://x.co/api/ModelA
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
X-Powered-By-Plesk: PleskWin
BODY view raw
<head>
<title>Document Moved</title>
</head>
<body>
<h1>Object Moved</h1>This document may be found
here
</body>

Download file from google cloud storage using ruby client gets HTTP redirect

I am trying to download a file from GCS using the Ruby client and Service Account authorization; here is my code:
def build_client
client = Google::APIClient.new()
key = Google::APIClient::PKCS12.load_key(SERVICE_ACCOUNT_PKCS12_FILE_PATH, 'notasecret')
service_account = Google::APIClient::JWTAsserter.new(
SERVICE_ACCOUNT_EMAIL,
'https://www.googleapis.com/auth/devstorage.full_control',
key)
client.authorization = service_account.authorize
client
end
client = build_client
storage = client.discovered_api('storage', 'v1beta2')
#Get (download) a specific object from a bucket
bucket_get_result = client.execute(
api_method: storage.objects.get,
parameters: {bucket: BUCKET, object: params[:file_name], alt: 'media'}
)
puts bucket_get_result.body
The result body is a redirect detail as follows:
<HTML>
<HEAD>
<TITLE>Temporary Redirect</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Temporary Redirect</H1>
The document has moved here.
</BODY>
</HTML>
...and then if I try to go to the redirect 'location' I get an Unauthorized HTTP. So, how can I download a file from GCS using the ruby client? https://developers.google.com/storage/docs/json_api/v1/objects/get says:
If you provide the URL parameter alt=media, then it will respond with the object data in the response body
The Google Ruby API client does not currently support downloading media.
However, you could always do the rest of the work yourself.
require 'httparty'
get_result = bucket_get_result = client.execute(
api_method: storage.objects.get,
parameters: {bucket: BUCKET, object: params[:file_name], :alt=>'media'})
url = get_result.response.env[:response_headers]['location']
token = "Bearer #{bucket_get_result.request.authorization.access_token}"
puts HTTParty.get(url, :headers => {"Authorization" => token}).body

Strophe session attachment -- 403 forbidden

I am working on an XMPP web application which need to include session attachment. I am using Openfire XMPP server. I have successfully implemented the server side attachments where the session is created and I get the sid and rid of a session. Unfortunately, I am stuck in the next part.
As I know, after getting the sid and rid, I need to use the Strophe.Connection.attach() to attach strphe to the existing session. After that I am making an IQ request which gets the correct response from the server. However, I am not getting any changes in the status i.e. the app is neither connected nor attached and hence I am not able to do anything.
After the IQ request, the server responds on time with the normal message and then in the next request, I get a 403 forbidden error and the connection is terminated.
Here is the code:
var BOSH_SERVICE = 'http://localhost/cosys-rtw/';
var connection = null;
var sid = "";
var rid = 0;
function notifyUser(msg)
{
if (msg.getAttribute('from') == "testuser1#ghost/pingstream") {
var elems = msg.getElementsByTagName('body');
var body = elems[0];
$('#notifications').append(Strophe.getText(body));
}
return true;
}
function onConnect(status)
{
console.log("Connect")
console.log(status)
if (status == Strophe.Status.ATTACHED) {
$('#notifications').html('<p class="welcome">Hello! Any new posts will appear below.</p>');
connection.addHandler(notifyUser, null, 'message', null, null, null);
connection.send($pres().tree());
}
}
$(document).ready(function () {
$.ajax({'url':'http://localhost/x',
'method':'get',
'success':function(response){
console.log(response);
console.log(jQuery.parseJSON(response));
resp = jQuery.parseJSON(response);
window.sid = resp.sid;
window.rid = resp.rid;
prepareStrophe();
}});
});
function prepareStrophe(){
console.log(BOSH_SERVICE);
jid = "testuser1#ghost";
connection = new Strophe.Connection(BOSH_SERVICE);
console.log(window.rid);
console.log(window.sid);
connection.attach( jid,window.sid,window.rid,null);
connection.sendIQ( $iq({to:Strophe.getDomainFromJid(jid),type:"get"})
.c('query',{xmlns:'http://jabber.org/protocol/disco#info'}),
function(){
if (status == Strophe.Status.ATTACHED) {
connection.send($pres().tree());}
});}
I get the follwoing response to the IQ request:
<body xmlns="http://jabber.org/protocol/httpbind">
<iq id="6173:sendIQ" xmlns="jabber:client" type="result" from="ghost" to="testuser1#ghost/6b8bfe07">
<query xmlns="http://jabber.org/protocol/disco#info">
<identity category="server" name="Openfire Server" type="im"></identity>
<identity category="pubsub" type="pep"></identity>
<feature var="http://jabber.org/protocol/pubsub#delete-nodes"></feature>
.
.
.
<feature var="http://jabber.org/protocol/pubsub#purge-nodes"></feature>
<feature var="http://jabber.org/protocol/disco#info"></feature>
<feature var="http://jabber.org/protocol/rsm"></feature>
</query>
</iq>
</body>
This response does say that the session is valid. Am I right?
I am not able to figure this thing so now I am handing this to the community.
By the way -- Merry Christmas
I think that I have got something here that I would like to share if anyone has the same problem. This thread on ignite realtime http://community.igniterealtime.org/thread/33004 discusses about this issue. The settings mentioned there did work for me.

Sending POST data to a page with a GET parameter with Nodejs

I'm trying to send POST data to a test.php file, which handles POST data only if it was provided a specific GET data. Unfortunately I have no clue how to do that; and have been searching for about an hour.
Any help would be appreciated, as i'm currently playing around a lot with this amazing stuff.
Thanks in advance;
Some clarification:
Say you have a index.php looking like this:
<?php
if (isset($_GET['p']))
echo count($_POST) . ' -- ' . count($_GET);
else echo 'fuuu';
?>
<form action="?p" method="POST">
<input type="submit" name="lolw" value="Go" />
</form>
If you submit that form, PHP's $_GET and $_POST superglobals will both contain 1 element.
Now, lets try to run that form through nodeJS.
Here is my test case (which is merely some cutpasting from the doku):
var http = require('http');
var options = {
hostname: 'localhost',
port: 80,
path: '/test.php?lolw=1&p',
method: 'POST'
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
}).on('error', function (e) {
console.log('error in chunk');
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.toString());
});
// write data to request body
req.write('data\n');
req.end();
CLI output gives for the body:
0 -- 2 and then follows the form.
My point is: is it possible to send some parameters through GET and some others through POST, and specifying which needs to be sent through GET and which through POST ?
To make an HTTP request in node.js, you'll need to use http.request. You can set the method to "POST" and still have get parameters in your URL. You'll need to set the Content-Length header to the length of your data and the Content-Type header to application/x-www-form-urlencoded for a "standard" POST request.
Your question is pretty vague. If you're having problems with something in particular, just show your code and ask the more precise question.