HTTP Post doesn't have BODY pin? (help with Philips Hue)

yeah, i need help on this…I have no idea how to send an http POST through the TCP node :(

while i’m here

this might do, untested tough.

HttpPostRaw.zip (2.9 kB)

woah, thanks woei!

it kinda works!

I loaded it up, like so:

{img src = “http://i.imgur.com/8Nbp7MI.png”}

The left pin is labelled header but the right pin has no label…is this supposed to be for the response?

As you can see I get a valid header from the Hue API but I don’t seem to be getting anything more…is this the node’s fault? Have I set it up wrong? Maybe it’s the API? (I’m using 45beta29.2 btw)

(I’ll attach the patch even though it won’t make much sense to anybody who doesn’t have the Hue setup)

thanks again, I’ll get this workin’ sooner or later!

HttpPostRaw-Test-01.v4p (4.9 kB)

ah yes, stream pins still new and a little tricky sometimes. take this code, should output something now. i’ve added comments to the code parts where i changed something.

- region usings
using System;
using System.ComponentModel.Composition;

using VVVV.PluginInterfaces.V1;
using VVVV.PluginInterfaces.V2;

using System.IO;
using System.Net;

using VVVV.Core.Logging;
- endregion usings

namespace VVVV.Nodes
{
	#region PluginInfo
	[PluginInfo(Name = "HTTP", Category = "Network", Version = "Post Raw",
	Help = "posts raw data to given urls on the web", Author = "woei")]
	#endregion PluginInfo
	public class HttpPostRawNode : IPluginEvaluate, IPartImportsSatisfiedNotification
	{
		#region fields & pins
		[Input("URL", StringType = StringType.URL, DefaultString = "http://localhost")](Input("URL", StringType = StringType.URL, DefaultString = "http://localhost"))
		ISpread<string> FURL;
		
		[Input("Content")](Input("Content"))
		ISpread<System.IO.Stream> FContent;
		
		[Input("MimeType", EnumName = "MimeTypeMode")](Input("MimeType", EnumName = "MimeTypeMode"))
		ISpread<EnumEntry> FMimeType;
		
		[Input("Refresh", IsBang = true)](Input("Refresh", IsBang = true))
		ISpread<bool> FRefresh;
		
		[Output("Header")](Output("Header"))
		ISpread<string> FHeader;
		
		[Output("Response")](Output("Response"))
		ISpread<System.IO.Stream> FResponse;

		[Import()](Import())
		ILogger FLogger;
		#endregion fields & pins
		
		public void OnImportsSatisfied()
		{
			// This ensures that we start in a clean state -> no null in FResponse,
			// which we'd need to take care of in each evaluate call.
			FHeader.SliceCount = 0;
			FResponse.SliceCount = 0;
		}

		//called when data for any output pin is requested
		public void Evaluate(int spreadMax)
		{
			FHeader.SliceCount = spreadMax;
			// We need to manage the lifetime of our streams
			FResponse.ResizeAndDispose(spreadMax, () => new MemoryStream());
			
			for (int i=0; i<spreadMax; i++)
			{
				if (FRefresh[i](i))
				{
					try
					{
						Uri url = new Uri(FURL[i](i));
						HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
						request.ContentType = FMimeType[i](i).Name;
						request.Method = "POST";
	        			request.KeepAlive = true;
						request.Credentials = System.Net.CredentialCache.DefaultCredentials;
						
						byte[]() buffer = new byte[1024](1024);
						int bytesRead = 0;
						using (Stream reqstr = request.GetRequestStream())
						{
							while [bytesRead = FContent[i](i).Read(buffer, 0, buffer.Length](https://vvvv.org/documentation/bytesRead-=-FContent[i](i).Read(buffer,-0,-buffer.Length) != 0) 
		            				reqstr.Write(buffer, 0, bytesRead);
	        			}
						
						WebResponse response = request.GetResponse();
						FHeader[i](i) = response.Headers.ToString();
						// Response stream doesn't support seeking -> getting Length not allowed
						FResponse[i](i).SetLength(response.ContentLength);
						using (Stream respstr = response.GetResponseStream())
						{
							while [bytesRead = respstr.Read(buffer, 0, buffer.Length](https://vvvv.org/documentation/bytesRead-=-respstr.Read(buffer,-0,-buffer.Length) != 0) 
		            				FResponse[i](i).Write(buffer, 0, bytesRead);
						}
						// Marks the pin as changed (as the pin doesn't know about write operation above)
						FResponse.Flush(true);
					}
					catch (Exception e)
					{
						FLogger.Log(e);
					}
				}
			}
		}
	}
}

EDIT: did a clean install of vvvv on a separate computer and the right pin is labelled “Response:” but I’m not getting any output

hmm…I pasted that code in place of the existing HttpPostRawNode.cs and the right output pin still isn’t labelled and doesn’t output anything :(

I just renamed woei’s code as old-HttpPostRawNode.cs and saved that code as HttpPostRawNode.cs, did I miss a step? I kept the same .csproj and didn’t touch anything in the bin and properties folders…

create new template (ctrl-click on template (value), put any name) and paste whole code in there

@zz it’s okey how you did it.
with the code elias posted you should see the response pin, which you do.

the issue with no data on the pin is actually something else. there’s really no response coming back. but i couldn’t figure out why exactly.

maybe some web wizzard knows what exactly you have to post to a server to get a response. just sending some string i get nothing back…

yeah it’s weird how the HEADER comes back but not the CONTENT/BODY/RESPONSE/WhateverIt’sCalled…aren’t they sent simultaneously?

I know that in my specific case (which may not be helpful), the header information coming out of the node is:

Pragma: no-cache
Connection: close
Access-Control-Max-Age: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Type: application/json
Expires: Mon, 1 Aug 2011 09:00:00 GMT

but the full plaintext response I see in a sniffer is:

HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Expires: Mon, 1 Aug 2011 09:00:00 GMT
Connection: close
Access-Control-Max-Age: 0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Content-type: application/json

[{"error":{"type":101,"address":"","description":"link button not pressed"}}]({"error":{"type":101,"address":"","description":"link button not pressed"}})

note: the ‘[{“error”:{“type”:101,“address”:"",“description”:“link button not pressed”}}]({“error”:{“type”:101,“address”:"",“description”:“link button not pressed”}})’ json is a good sign, and exactly what I’m looking to receive, so no problem there

don’t know if that helps at all, but there you go

request.KeepAlive = true;

was causing troubles

here we go

HttpPostRaw.zip (88.4 kB)

no luck, still getting all the header information but no output on the body

{img src = “http://i.imgur.com/Ieuy01B.png”}

Would this have anything to do with the header info(s) being outputted as a string but the body coming out as RAW?

Also, oddly, despite the header coming through it marks it as failed…

ok next attempt :)

seems as if the content-length property doesn’t need to be set - so modified that part that it can deal with both cases. oh and open up a tty node if your requests fail. should give you a little more info what’s going on. i’ve also added a new enum to the node “Method”, where you can select whether it’s a GET/POST/etc. request method. so be careful to set that one to POST in your case.

HttpPostRaw_1.zip (3.4 kB)

it…

it…

it…

{img src = “http://i.imgur.com/tAJAfq9.gif”}

IT WORKS!!!

{img src = “http://i.imgur.com/WJhbYoa.png”}

thanks so much antokhio & Elias & woei !!

next up I have to send some PUT commands but I have a good feeling those will work out fine!

Good to read it works :)

Would be nice if you can this a contribution, so we can add the Philips Hue to our “up and running” hardware collection, or at least post a patch. :)

Sure!

Workin on it right now!

What’s the best way to include the HTTPPostRaw node in a contribution?

bad news,

i’ve put POST through it’s paces and it works great, but PUT gives me a failed error…here’s what I get from the TTY window:

Stacktrace:
   at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting)
   at System.Net.ConnectStream.System.Net.ICloseEx.CloseEx(CloseExState closeState)
   at System.Net.ConnectStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at VVVV.Nodes.HttpPostRawNode.Evaluate(Int32 spreadMax)

InnerException:
System.IO.IOException: Cannot close stream until all bytes are written.
   at System.Net.ConnectStream.CloseInternal(Boolean internalCall, Boolean aborting)

That make sense to anybody?

Thanks again!

well, crap

i’m stuck here until i can do a PUT request,

can anybody take a look and help me out?

appealed to Elias and woei directly through PM’s, but if anybody else can help out that would be great!

i really want to get these Hue bulbs up and running, and without PUT requests I’m totally stuck

Turns out all the problems here are totally my fault after all, I was aiming at the wrong IP after resetting my router among other things…so the PUT requests work out fine!

PROBLEM IS…the node is just SLOW…really much too slow for my tastes, is this the result of it being raw code? Would it be faster if it was ‘compiled’ somehow or something like that?

Right now I’m looking at a solution using ShellExecute (Windows) and http://curl.haxx.se/ that is much faster, but lacks the full two-way communication…

I’ll post the patches as I finish them up, though!

try exec