LSL Wiki : llHTTPRequest

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are c-71-202-89-105.hsd1.ca.comcast.net
key llHTTPRequest(string url, list parameters, string body)

Sends HTTP request to url with the specified body and parameters.

url must always be a valid HTTP or HTTPS URL, pointing to a location outside the Linden Lab and Second Life servers.

parameters is a list of <integer key, string value> pairs:
parameter Value Type Default Description
HTTP_METHOD 0 string "GET" "GET", "POST", "PUT" and "DELETE"
HTTP_MIMETYPE 1 string "text/plain;charset=utf-8" text/* MIME types should specify a charset. To emulate HTML forms use application/x-www-form-urlencoded. This allows you to set the body to a properly escaped (llEscapeURL) sequence of <name,value> pairs in the form var=value&var2=value2 and have them automatically parsed by web frameworks (PHP will allow you to retrieve them from $_POST) (Supported in version 1.10.4)
HTTP_BODY_MAXLENGTH 2 integer 2048 (Setting HTTP_BODY_MAXLENGTH is not yet supported)
HTTP_VERIFY_CERT 3 integer TRUE If TRUE, the server SSL certificate must be verifiable using one of the standard certificate authorities when making HTTPS requests. If FALSE, any server SSL certificate will be accepted. (Supported in version 1.10.4)

Although the HTTP_AUTHORIZATION parameter is not available, you may still login to websites requiring basic authentication by formatting your url appropriately:
string username = "Your Name";
string password = "Your Password";
string url = "http://" + llEscapeURL(username) + ":" + llEscapeURL(password) + "@domain.com/page.php";

body specifies the body of the HTTP request and is only used when HTTP_METHOD is POST or PUT. The body is only limited to the amount of available free memory in the script (before the script has a stack/heap collision.) (As of 10/29/06 this seems to be limited to 2048 characters, and cuts off anything further - Seifert)

The key returned by llHTTPRequest uniquely identifies the request and is passed to the http_response() event handler along with the request results when the request completes.

HTTP requests made using llHTTPRequest are throttled based on the script owner and region. Requests are throttled to a maximum of 20 requests per 100 seconds. See this thread (or this page) and this thread (or this page) for more details.
NOTE: This has been changed to 100 requests per 100 seconds now.

If any errors are found in the parameters given to llHTTPRequest, or the HTTP request cannot be made as the owner has exceeded the allowed request rate, then the returned key will be set to NULL_KEY and error messages will be sent to the debug channel.

The following headers are added to HTTP requests made by llHTTPRequest:

Header Value Description
Accept text/*
Accept-Charset utf-8;q=1.0, *;q=0.5
User-Agent Second Life LSL/VERSION (http://secondlife.com/) simulator version making the request
X-SecondLife-Shard SHARD "Production" if the HTTP request is made from SL; otherwise, "Testing"
X-SecondLife-Object-Name NAME object name making the HTTP request
X-SecondLife-Object-Key KEY object UUID making the HTTP request
X-SecondLife-Region NAME(X,Y) region containing the object making the request; X,Y is its grid location
X-SecondLife-Local-Position (X,Y,Z) object region coordinates making the request
X-SecondLife-Local-Rotation (X,Y,Z, W) object quaternion rotation making the request
X-SecondLife-Local-Velocity (X,Y,Z) object velocity making the request
X-SecondLife-Owner-Name NAME object owner name making the HTTP request This will be group if the object is deeded to group
X-SecondLife-Owner-Key KEY object owner key making the HTTP request This will be group if the object is deeded to group
Note, some languages may export the X-SecondLife-* variables differently, however the HTTP headers send it as X-SecondLife-Shard and similar, with an ASCII hyphen, and no prefix before X; these are also not LSL constants in the variables and conform to HTTP header specifications, not LSL specifications. - Ice

This lets some very useful things be done, such as getting keys from key databases. Example, using the w-hat.com database:

//Quick hack to find and display resident's keys from the w-hat name2key database
//  Keknehv Psaltery, 5/5/06

key requestid;
string resident;

default
{
    state_entry()
    {
        llListen(1,"","","");
    }
    listen( integer chan, string name, key id, string msg )
    {
        list names = llParseString2List(msg,[" "],[]);
        resident = llDumpList2String(names," ");
        requestid = llHTTPRequest("http://w-hat.com/name2key?name="+llDumpList2String(names,"+"),[HTTP_METHOD,"GET"],"");
    }
    http_response(key request_id, integer status, list metadata, string body)
    {
        if (request_id == requestid)
        {
            integer i = llSubStringIndex(body,resident);
            if ( i != -1 )
                llSay(0,llGetSubString(body,i,i+llStringLength(resident)+36));
            else
                llSay(0,"No resident named \""+resident+"\" found in the w-hat name2key database");
        } else
            llSay(0,(string)status+" error");
    }
}

Note: Requests currently come from

64.129.40.0/23
66.150.244.0/23
69.25.104.0/23
72.5.12.0/22

Source


An example of using llHTTPRequest/http_response with your own PHP Server


Functions | Communications
Comments [Hide comments/form]
This function currently as of preview 1.9.1 doesn't pass the Content-type or Content-length headers, making it impossible for PHP (not sure about Perl, Ruby on Rails, Cold Fusion, etc.) to parse POST data automatically and place it into the $_POST superglobal array. I've wrote a simple PHP snippit to replicate what PHP does. Currently it's not multidimensional, but if somebody wants it I'll write that in too. This should work on all servers. Also, look into using llEscapeURL to escape your data especially if it contains unsafe characters (such as spaces, or ampersands), but beware of its limitations; you may wish to write a wrapper function to make sure you do not encounter it.

<?php
$p_data 
implode(''file('php://input'));
$p_data explode('&'$p_data);

foreach (
$p_data as $p_val) {
    
$d_parts explode('='$p_val);
    
$_POST[$d_parts[0]] = urldecode($d_parts[1]);
}

// All POST variables now loaded into $_POST and can be processed normally.
?>
-- VeloxSeverine (2006-04-16 21:52:07)
Ruby has no trouble getting at the post data via the params hash, and the headers through request.env. It seem that all these headers aren't implemented yet though. I can see X-SecondLife-Shard & X-SecondLife-Object-Name but none of the others. Am I going mad?
-- KermittQuirk (2006-04-18 07:24:14)
They're all implemented...at least in 1.9.1 (11). I just ran a test and all of them showed up.

On an unrelated note, as of 1.9.1 (11) HTTP_BODY_MAXLENGTH and HTTP_MIMETYPE are not accepted parameters, and return a "not recognized" script error upon execution.
-- VeloxSeverine (2006-04-18 18:09:48)
Hmm, is it just my imagination, or does this function refuse to connect to any port besides 80?
-- SchizzySapeur (2006-04-18 21:57:07)
I was able to successfully connect to a server on port 3000. Did you use a valid HTTP url (including the http: etc.)? Also, note that SSL (https) cannot be used at this time, though being a cURL implementation it wouldn't be too hard, as long as they only accepted valid certificates.
-- VeloxSeverine (2006-04-19 01:26:07)
OK I must be doing something wrong. Just retested in 1.9.1 (13) and I'm still only getting the two of them. Could you explain how you tested it? I'm probably just looking in the wrong place cause I'm still pretty raw with Ruby. Couldn't find them using php either though. If someone could produce some Ruby + LSL code that'd be ideal, but any any working example would be appreciated irrelevant of the language. I should be able to figure it out from there anyway.
-- KermittQuirk (2006-04-21 03:21:09)
Well, after the hardware upgrade only two sims are correctly using llHTTPRequest (Cayman and Darkwood), and in PHP I used apache_request_headers(), which currently only works on Apache and a few other servers. As for Ruby, I'll try and write up an example later. If you want to discuss it further (comments probably aren't the best place), just IM me inworld.
-- VeloxSeverine (2006-04-21 20:18:27)
I've posted on the forums about the headers. http://forums.secondlife.com/showthread.php?t=101938
Looks like my problems came from the fact that body never contains more than 512 bytes. Not sure if this is a limitation on llHTTPRequest or something else causing it.
-- KermittQuirk (2006-04-21 23:48:53)
I think there's something else causing it for you there, as I've been able to retrieve a maximum of 2049 bytes. I've posted more in the forums, and edited the wiki pages with my results.
-- VeloxSeverine (2006-04-22 09:29:42)
Sitting here in Preview 1.10.0(27) and it still looks like the Content-Length header is still not being propagated in the request... still needing to use Velox's $_POST solution.
-- BinoArbuckle (2006-05-17 17:43:24)
It works on the latest preview version 1.10(29) It places the variables correctly
-- NekosuneSmails (2006-05-19 21:55:58)
I'm not entirely sure of that... Content-Type being reported via SL is 'text/plain;charset=utf-8' whereas if I use curl -d or do an HTML form to the same thing, Content-Type is being reported as 'application/x-www-form-urlencoded'.
-- BinoArbuckle (2006-05-21 12:39:09)
The solution to this problem is the yet unimplemented HTTP_MIMETYPE. The default mime type of text/plain;charset=utf-8 is technically a correct choice for the posting, and does meet RFC requirements as far as I am aware. However, since it does not detect the mime type automatically (which would probably be flawed anyway), we will just have to wait for HTTP_MIMETYPE to be implemented.
-- DirtyMcLean (2006-05-22 13:56:14)
Right. Because I'm dense and don't understand HTTP all that well, could someone be oh-so-kind as to post a server-side example of this (preferably in PHP)?
-- DolusNaumova (2006-06-01 13:27:12)
I'm rather upset both at the posting of code which consults a name to key database as well as I'm even more upset at the very idea that such a database exists. While it's true that it's fairly easy to get a key manually by looking at the debug console, it is a serious violation of privacy. Do we really want this code on here? The group that has made this code is notorious for going around harrassing people, not to mention at least two attempted grid-wide crashes, at least one of which was actually successful. I personally can see no reason whatsoever to have a name to key database short of using scripts on a user for the purpose of harrassment, such as spamming them with given objects or one thing w-hat has done in the past, llDialog spam. There's any number of ways this can be abused and I seriously suggest we replace it with something far less likely to be abused.
-- LuccaKitty (2006-06-06 12:27:43)
i disagree Lucca, also itsnot the only name2key database publicly available
-- KyrahAbattoir (2006-06-06 15:55:15)
I just finished making a test daemon in that grabs the SL specific headers for a get request from http requests. Now while looking at all of the data involved, it suddenly occured to me. The "Shard" is essentially which grid. Production is the live grid. Testing is the test grid. There are two other grids that it might be useful. The first is i think the most useful, the teen grid or "shard". Then you have the cornfield. Do those have a seperate shard name? Because I'd like to be able to add the ability to detect that and react appropriately.
-- LuccaKitty (2006-06-06 16:21:21)
w-hat is not responsible for those attacks as is made clear on their website.
-- DolusNaumova (2006-06-08 07:54:16)
Yes, believe everything you read, Dolus. "It must be truth, it's on the intarweb!" You know, noone in prison is guilty, they all state very matter of factly that they did not commit the crime they were convicted of. The fact is that I've seen far too much out of them with my *OWN EYES* to believe a word they say. The fact is that too many of them have actually lied DIRECTLY TO MY FACE about things and entered into FALSE friendships with me with the SOLE purpose of DECIEVING me for me to believe ONE IOTA of what they say.
-- LuccaKitty (2006-06-08 22:07:47)
Like, whoa. Please refrain those types of comments? They're kind of offtopic and useless to this page and tp the users that want to properly use it.
-- DavidGall (2006-06-14 09:34:36)
Hooray! HTTP_MIMETYPE is now supported (10.4). For posting to PHP, use the params [HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"]
-- DirtyMcLean (2006-06-21 10:15:39)
Yes the additions to 10.4 are nice. Is it possible to append authentication header to the http request for various web based services that use it? I need to add "Authentication: Realm token=blahblahblah" to a POST method header.
-- ChanceUnknown (2006-06-21 12:51:31)
Is it just me or does the http example above fall 5 characters short?
-- ArtemisLatrell (2006-07-08 15:41:20)
Anyone else getting a (waiting) value for HTTP_X-SecondLife-Owner-Name??? or is it just me?
I have been pulling owner name from the header info for neighbours project, and many peoples names are showing up as (waiting)
-- MaxCase (2006-07-08 19:27:08)
Two notes:
1) The additional headers add all start "X-SecondLife", not "HTTP_X-SecondLife". The CGI specification causes the prefix "HTTP_" to be added when these headers are placed in the environment variables. PHP duplicates this behavior when it adds them to its global variables. However, not all HTTP frameworks do this. In fact, even in PHP, when fetching the headers via the function apache_request_headers() the header names will be prefixed. Hence, I have edited the names of the headers to the actual form.
2) You will see "(waiting)" for the X-SecondLife-Owner-Name if the region hasn't yet fetched the owner name information. The implementation decided not to stall the HTTP call waiting for that information if it isn't present since many uses of HTTP don't need it.
-- ZarfVantongerloo (2006-07-09 15:14:46)
thanks zarf
-- MaxCase (2006-07-09 18:15:06)
er, typo: In my comment above, it should read: "... via the function apache_request_headers() the header names will NOT be prefixed."
-- ZarfVantongerloo (2006-07-09 19:28:50)
Added content of forum posts on separate WakkaWiki pages, for the benefit of the ones that are unable to see them on the forums.
~~~~
-- GwynethLlewelyn (2006-07-30 15:51:04)
... and I'm soooo glad I've waited some versions until HTTP_MIMETYPE application/x-www-form-urlencoded was developed :) :)

It works wonderfully well!
-- GwynethLlewelyn (2006-07-30 17:50:29)
For greater server compatibility and efficiency, use $_SERVER[] instead of apache_request_headers() to access the SL header data.
No need to have PHP as apache module for access to header info.

For Example, $_SERVER['HTTP_SECONDLIFE_OWNER_NAME']; (notice the header name format)
-- PlexLum (2006-08-06 20:36:55)
PlexLum, that is a good tip :) Was about to post that myself the other day :)
-- BirdRaven (2006-08-08 09:39:53)
Thanks BirdRaven, I found it quite strange to require apache for access to header data! ^^

I noticed I forgot to put the _X_ in my example.
It should read $_SERVER['HTTP_X_SECONDLIFE_OWNER_NAME'];
-- PlexLum (2006-08-09 03:16:23)
Someone had replaced X-SecondLife-* headers with the PHP language method, calling apache_request_headers(); returns an array containing X-SecondLife-* headers, I noted also that some languages will change this. I have seen at least 1 script corrupted by the HTTP_X_SECONDLIFE_* edit and lack of testing, thus I reverted it.
-- IceBrodie (2006-08-25 16:22:51)
Sorry for not using $_SERVER[]; I sadly am no PHP expert and mostly posted that snippet of code for a friend.

Thanks for the great tip!
-- GwynethLlewelyn (2006-08-28 16:28:39)
Although I've used HTTPRequest quite happily with some RSS feeds, it appears to fail when getting others (specifically those from the BBC), giving an Unknown/Unrecognised Content-Type error. Looking at the headers it appears to work OK when the RSS is sent as text/xml but fails when it is sent by the server as application/xml. Is this a gap in the HTTPRequest implementation or am I missing something?
-- CorroMoseley (2006-09-03 08:15:05)
Oops. RTFM. Found the bit in http_response where it says it only handles text/ content. Any chance of changing this?
-- CorroMoseley (2006-09-06 12:42:00)
Nothing we can do, ask the lindens, they dont use or view this wiki.
-- BirdRaven (2006-09-08 09:52:45)
Actually, we Lindens do indeed use, view, and write in this wiki. In fact, when we released llHTTPRequest(), the first thing we did that morning was come here and start this page!

Anyway, yes, only text is supported as LSL isn't rich enough to support other data types. What would we do with image/jpeg? I suppose that we could return the bytes as some sort of base64 encoded string -- but really, how useful would that be?

Now, "text/xml" vs. "application/xml" are another matter: The problem has to do with character sets. With "text/xml", as with all "text/*" MIME types, the character set of the content comes from the headers. Hence, we can correctly interpret the body and put it into an LSL string (which is Unicode externally, and UTF-8 internally). With "application/xml", the character set is declared in the XML body itself. This means that we'd have to actually parse at least some of the body to be able to determine how it was encoded, so we could then properly transcode it into an LSL string. This option didn't look appealing due to resource requirements. But, I understand the desire, and it is possible we could add such support in the future.
-- ZeroLinden (2006-09-25 10:00:41)
It's true; nat.janus.lindenlab.com is currently something like the 20th top-ranked host for total pageviews. Which means that there are about 20 people who hit the wiki more than all the Lindens combined. Regardless, they most definitely do use it. I can tell. ;)
-- CatherineOmega (2006-09-25 21:06:28)
If http_response(...) is an event, like state_entry(), why it has not the same color (blue-ish)?
-- AlphonsJano (2006-10-08 16:25:43)
There seems to be a current limitation to 2K bytes in the response body.
This is a pretty severe limitation, though I can see why you might want
an upper limit you can enforce. But how about some better control on which
bytes you get?

In order of preference, here are some suggestions:

1. implement the HTTP_BODY_MAXLENGTH parameter as described.

2. provide a way to specify *which* 2k bytes of the body you get, via
a new parameter, say HTTP_BODY_OFFSET, which would discard the first
HTTP_BODY_OFFSET bytes from the response and then include the next
HTTP_BODY_MAXLENGTH, or 2k, or whatever, bytes.

3. provide a way to insert the HTTP header "Range" into the request.
This allows a specific byte range to be returned from the server, but
it will only work for HTTP 1.1 compliant servers that do this right.

Any chance of one or more of these suggestions being implemented any
time soon?
-- SumiIzumi (2006-12-07 18:22:42)
Regarding my previous comment, a this point I am not 100% sure it was truncating to 2K.
However, I think my suggestion still stands - whatever your upper limit is, providing a way
to use an offset into the results would be useful.
-- SumiIzumi (2006-12-08 03:18:45)
Is there away to get around basic authentication by adding our own headers somehow? The parameters don't seem support HTTP_AUTHORIZATION.
-- c-68-50-131-158.hsd1.va.comcast.net (2007-03-23 19:19:03)
What are the certificates recognized when HTTP_VERIFY_CERT is set to TRUE?
-- DaleGlass (2007-04-30 07:38:43)
For page offsets I ended up just using another PHP script to load a page, cache it, and provide 2047 bytes at a time determined by the "page" passed to it until an an end token which would erase the cached page and stop the script from requesting the next "page." Not that elegant but it works and uses less bandwidth on LL's part, as they only have to load 2k at a time, not a whole 10k document over and over.
-- VeloxSeverine (2007-06-26 13:23:23)
Attach a comment to this page: