goToUrl with postData

Hi all!

I would like to call a browser (that is not visible on the window, I need it only for the request send) to go to a specified url, with POST data in it.
goToUrl has 3 parameters, first is the address itself, second is the headers and third is the post data.

My question is: how should I set the headers, and what type of data should I put in the postData MemoryBlock to be able to get the POST results in the destination php page?

Some code, maybe it helps to debug:

[color=#00BF00]//the MemoryBlock I want to send[/color]
MemoryBlock* toPost = new MemoryBlock();

[color=#00BF00]// the data I want to send[/color]
toPost->append(“x=y&u=v”,7);

StringArray* headers = new StringArray();
[color=#00BF00]// I tried to set the headers to something I found on the net
// but it must be be incorrect as it just doesn’t work[/color]
headers->add(“Content-Type = application/x-www-form-urlencoded”);

[color=#00BF00]// let’s say needPost.php just prints the POST array to the screen
// so if it would work correctly, it would show “x : y” and “u : v” or something similar [/color]
browser->goToURL( “http://something.com/needPost.php”, headers, toPost );

Thanks,
rolanddd

Why not just use the URL class to do the post? Having a whole browser sitting there offscreen seems crazy if you’re just trying to send information to a server…?

True, but I didn’t find anything to call the URL with. Which function should I use?

This is not the best way to do it. But you can make the post variable part of your url. Something like http://www.google.co.in/search?q=url. This would search for url.

I had used “copyFrom (const void *srcData, int destinationOffset, int numBytes)”, to append data from a juce string to memoryblock. And hadn’t set any header information. Am sorry I could find the code. Will get back to you if I can find it.

URL::createInputStream(), or URL::readEntireTextStream(), or URL::readEntireXmlStream(), etc… I don’t think I made those methods particularly hard to find!

Hi Jules,
[quote]InputStream* URL::createInputStream ( const bool usePostCommand,
OpenStreamProgressCallback *const progressCallback = 0,
void *const progressCallbackContext = 0,
const String & extraHeaders = String::empty,
const int connectionTimeOutMs = 0
) [/quote]

If I need to post a variable, can I send it as a part of extraHeaders?

You’d just add your variable to the URL as a parameter, and let the URL class deal with it. The header fields are really just for advanced HTML stuff.

I tried like this:

[color=#00BF00]/*
post.php contains:
Welcome <?php echo $_POST["fname"]; ?>!

You are <?php echo $_POST["age"]; ?> years old.
/[/color]
URL
url = new URL([color=#FF0000]“http://127.0.0.1/post.php”[/color]);
url->withPOSTData([color=#FF0000]“fname=Roland&age=21”[/color]);
[color=#00BF00]// I use a TextEditor to see the result[/color]
textEditor->setText(url->readEntireTextStream([color=#0040FF]true[/color]), [color=#0040FF]false[/color]);

But it just doesn’t work. After a warning (that suggests me to break the build, but I choose continue so I can see the result) I can’t see any values of the desired fname and age variables. Any ideas?

Oh dear…

URL is immutable. withPostData is a const method! It returns a new object, it doesn’t alter the one you apply it to.

URL url ("http://blah"); url = url.withPostData ("foo"); url.readEtc..

But you don’t even need to use withPostData:

URL url ("http://foobar"); url = url.withParameter ("age", "21") .withParameter ("foo", "bar");

would handle it all for you…

Thank you very much!!! :slight_smile:
Sorry, I’m a beginner with Juce (as you noticed).
Cheers

I have one more problem. ( I didn’t have any problems with it in Windows only under Linux, which is strange)
I set the URL as you advised (using withParameter(), but I also tried withPOSTData() just to make it sure) then I wanted to readEntireXmlStream().
Two cases:

  • when the usePostCommand parameter is set to false, it worked, but I get an Assertion failure in juce_amalgamated.cpp line 247968 (xxx todo is written there, so I guess you will correct it later) but it’s not so interesting for me since I do want to use with POST

  • but when usePostCommand is set to true, after calling a getFirstChildElement() function on the returned XML I get a Segmentation fault (because readEntireXmlStream returns 0 - this is the case, when it fails), no matter if the URL was withParameter()-ised or not

I also tried readEntireTextStream() just to print out what I want to parse, and had the same results. (returns an empty string when usePostCommand is set to true)

Again, this occurs only under Linux. Is there any solution to my problem?

…well yes, obviously you’ve got to check that it’s not a null pointer before you go calling methods on it!

There could be any number of reasons why it’s failing to read the stream, but the assertion that you hit (which I assume is the one in juce_getInternetFileContentLength?) won’t affect it, it’d work fine without that. If you can show me some code in the linux stack that’s not doing its job, I’ll take a look.

Now this is something weird. I tried to run the program from a different location and surprisingly it works here :o I’ve just read your post, and I started to run with gdb to print what’s going on, and I got this message

[code][Thread debugging using libthread_db enabled]
JUCE v1.50
[New Thread 0xb7fe3b70 (LWP 2699)]
[New Thread 0xb75ffb70 (LWP 2700)]
JUCE Assertion failure in src/…/…/…/juce_amalgamated.cpp, line 247968

Program received signal SIGTRAP, Trace/breakpoint trap.
0x006e0422 in __kernel_vsyscall ()
(gdb) c
Continuing.
[Thread 0xb75ffb70 (LWP 2700) exited]
[Thread 0xb7fe3b70 (LWP 2699) exited]

Program exited normally.
[/code]
I was like, wow, it has some trouble with the same line I mentioned before (btw you’re right, it’s in int64 juce_getInternetFileContentLength (void* handle) ) but still, it worked! I thought for a sec, it’s because gdb, but of course not :slight_smile: it works without gdb as well with the assertion failure:

JUCE Assertion failure in src/../../../juce_amalgamated.cpp, line 247968
The previous connection was through WiFi (ADSL), and now I’m behind a proxy with cable, and here it works…

I have an other question about URL. I want to upload files with a script, that needs 3 parameters.

fileUrl = fileUrl.withParameter("dir","folder/"); fileUrl = fileUrl.withParameter("filename",fileInfo.filename); fileUrl = fileUrl.withParameter("file",file.loadFileAsString());
This works fine with files that contain plain text, but it won’t work with files like images, executables, so anything that can’t be converted to string format.
So I thought instead of the last withParameter I would use

but the script won’t work like this. it says I’m passing nothing, so it just can’t see the file parameter. I don’t understand why, since the name of the parameter is “file” like with the withParameter function, and I’m passing the same file I passed before as a string. How could I solve it?

I think you answered your own question in saying you weren’t giving it a mime type. You’ve got to give it a mime type or it ain’t going to work!

Now I set the mime type but the webscript keeps telling me I’m passing null. I assume the script is correct, since it worked with withParameter (and text files). Some examples of the mimes I set:

  • jpg : “image/jpeg”
  • zip : “application/zip”
  • doc : "application/msword"
    and so on… Is it fine, or does juce use any different types? (I doubt, though)

Hi Jules,
Does URL class code has issues with Wi-fi connection on linux. I haven’t come across any issues on Macintosh.

[quote=“rolanddd”]Now I set the mime type but the webscript keeps telling me I’m passing null. I assume the script is correct, since it worked with withParameter (and text files). Some examples of the mimes I set:

  • jpg : “image/jpeg”
  • zip : “application/zip”
  • doc : “application/msword”
    and so on… Is it fine, or does juce use any different types? (I doubt, though)[/quote]

Juce doesn’t look at the mime type. And I don’t think anything on the local machine would care either. If the webserver is complaining, it usually means that the type didn’t match the file.

[quote=“vishvesh”]Hi Jules,
Does URL class code has issues with Wi-fi connection on linux. I haven’t come across any issues on Macintosh.[/quote]

Well no - the transport layer is way below anything that juce would deal with. It just opens a socket, it doesn’t care or know how the data gets sent, that’s the job of the OS.

Sorry it’s me again, I just can’t get over with it. I’m using an url that has a parameter at the end (simple GET parameter) needed for authentication URL fileUrl("http://localhost:8080/.../upload?auth="+auth);
I also want to use the parameters with POST as I mentioned before. Well if I’m using them, it works fine (but I can’t upload any files containing non-textual data)fileUrl = fileUrl.withParameter("path","Upload/Files/"); fileUrl = fileUrl.withParameter("filename",localInfo.filename); fileUrl = fileUrl.withParameter("file",fileToUpload.loadFileAsString()); requestResult = fileUrl.readEntireTextStream(true);
but when I append my file with the withFileToUpload function, it won’t work. //using this function instead of the last withParameter fileUrl = fileUrl.withFileToUpload("file",fileToUpload,mimeType); The problem starts already with my authentication. I’m getting an auth error from the server. I guess that means when I’m using withFileToUpload, my GET parameter disappears from the url. I tested it without the other POST parameters, only with the file, has the same result. I also tried to print the content of the “file” parameter fileUrl.getParameters().getValue("file","no file") and I got “nofile” as a result (that’s the default return value). So I don’t get it. How does the file-to-be-uploaded exist in the request? I mean how can I reach it? I know it’s there (I printed out fileUrl.getFilesToUpload().getValue(“file”,“nothing”) and I got the filename with path just fine) so there must be a way for these methods to work together. Did I miss something?

fileUrl = fileUrl.withParameter("path","Upload/Files/");
fileUrl = fileUrl.withParameter("filename",localInfo.filename);
fileUrl = fileUrl.withParameter("file",fileToUpload.loadFileAsString());
requestResult = fileUrl.readEntireTextStream(true);

Looks like you are sending the contents of the file as a string. Don’t think that is the right way to upload a file.

You should be using “fileUrl = fileUrl.withFileToUpload(“file”,fileToUpload,mimeType);” for both text and binary file. Please check if this works for text file. If not it could be problem on the server side.

P.S. You should have a web application(web-page) to check if upload actually works on the server end.