Difference between revisions of "LSL HTTP server"
Spore Static (talk | contribs) |
Fenchurch Oh (talk | contribs) m (Previous text "Testing this have it has been found that..." made ZERO sense.) |
||
(37 intermediate revisions by 19 users not shown) | |||
Line 1: | Line 1: | ||
{{LSL Header|ml=*}} | {{LSL Header|ml=*}} | ||
= Introduction = | |||
This is the counterpart to [[llHTTPRequest]]. While [[llHTTPRequest]] enables [[Script|LSL scripts]] to request data from HTTP-accessible sources, HTTP-in enables outside sources to request data from [[Script|LSL scripts]] in Second Life. The key difference is that [[llHTTPRequest]] exchanges data when the script in SL wants; HTTP-in allows outside sources to determine when they need to communicate with [[Script|LSL scripts]] in SL. | |||
Prior to HTTP-in, similar functionality could be achieved by [[HTTP Polling|polling]] with [[llHTTPRequest]], [[llEmail]] and [[:Category:LSL_XML-RPC|XML-RPC]]. All three are cumbersome and the latter two have serious scalability bottlenecks. | |||
* Easily get data from LSL scripts to outside viewers, scripts or servers. | |||
It is important to note that [[LSL HTTP server|LSL HTTP servers]] cannot use [[llSetContentType]] with [[CONTENT_TYPE_HTML]] for an [[llHTTPResponse]] except in very limited circumstances. See [[#Other_Limitations|Other Limitations]] for details. | |||
'''This section forms the [[:Category:LSL HTTP#Understanding_LSL_HTTP_Communications | Incoming]] HTTP pipeline.''' | |||
= Uses = | |||
* Easily get data from [[Script|LSL scripts]] to outside viewers, [[Script|LSL scripts]] or servers. | |||
** Web front end for a visitor counter or other statistics accumulator. | ** Web front end for a visitor counter or other statistics accumulator. | ||
* Easily get data into LSL scripts from outside viewers, scripts or servers. | * Easily get data into [[Script|LSL scripts]] from outside viewers, [[Script|LSL scripts]] or servers. | ||
** A store with a web front end that communicates to an in-world object to exchange L$ and inventory items. | ** A store with a web front end that communicates to an in-world object to exchange L$ and inventory items. | ||
** | ** Inworld game for which an external program handles the primary game logic that needs to manipulate inworld items. | ||
* HUD UI when used with [[llSetContentType]]. See [[HTML HUD Demo]]. | |||
Gory Technical Details follow. Or jump straight to the [[LSL_http_server/examples | Script Examples]]. | |||
= Script API = | |||
== | == Events == | ||
* '''[[ | * '''[[http_request|http_request(key id, string method, string body)]]''' | ||
: Event triggered when an URL is hit: | : Event triggered when an URL is hit: | ||
:* id is unique to this request | :* id is unique to this request | ||
:* Supported methods are GET/POST/PUT/DELETE | :* Supported methods are <code>"GET"</code>, <code>"POST"</code>, <code>"PUT"</code>, <code>"DELETE"</code> | ||
:* body: The body of the request. | :* body: The body of the request. | ||
: Event also triggered with response to | : Event also triggered with response to [[llRequestURL]] and [[llRequestSecureURL]] | ||
:* id matches the key returned by | :* id matches the key returned by [[llRequestURL]] or [[llRequestSecureURL]] | ||
:* method == [[URL_REQUEST_GRANTED]] for success, [[URL_REQUEST_DENIED]] for failure to get an URL | :* method == [[URL_REQUEST_GRANTED]] for success, [[URL_REQUEST_DENIED]] for failure to get an URL | ||
:* body is the public URL. | :* body is the public URL. If unable to get a public URL body will be empty. | ||
* '''[[Changed|changed(integer change)]]''' | * '''[[Changed|changed(integer change)]]''' | ||
:* [[CHANGED_REGION_START]]: New changed | :* [[CHANGED_REGION_START]]: New [[changed]] [[event]] triggered on region startup. | ||
* | :* [[CHANGED_REGION]]: New [[changed]] [[event]] triggered when crossing regions or teleporting. Please read [[CHANGED_REGION]] for more info. | ||
:* [[CHANGED_TELEPORT]]: New [[changed]] [[event]] triggered when the avatar teleports. Please read [[CHANGED_TELEPORT]] for more info. | |||
== Functions == | |||
{{LSL Function/Head | |||
|func_id=345|func_sleep=0.0|func_energy=10.0 | |||
|func=llRequestURL | |||
|func_desc=Requests one HTTP:// url for use by the script. The [[http_request]] [[event]] is triggered with the result of the request. HTTP-in uses port 12046. | |||
|return_type=key|return_text=that is the handle used for identifying the result in the [[http_request]] [[event]]. | |||
|func_footer | |||
|caveats=none | |||
}} | |||
{{LSL Function/Head | |||
|func_id=346|func_sleep=0.0|func_energy=10.0 | |||
|func=llRequestSecureURL | |||
|func_desc=Requests one HTTPS:// (SSL) url for use by the script. The [[http_request]] [[event]] is triggered with the result of the request. HTTPS-in uses port 12043. | |||
|return_type=key|return_text=that is the handle used for identifying the result in the [[http_request]] [[event]]. | |||
|func_footer | |||
|caveats=none | |||
}} | |||
{{LSL Function/Head | |||
|func_id=347|func_sleep=0.0|func_energy=10.0 | |||
|func=llReleaseURL | |||
|p1_type=string|p1_name=url|p1_desc=URL to release | |||
|func_desc=Releases the specified URL, it will no longer be usable. | |||
|func_footer | |||
|caveats=none | |||
}} | |||
{{LSL Function/Head | |||
|func_id=348|func_sleep=0.0|func_energy=10.0 | |||
|func=llHTTPResponse | |||
|p1_type=key|p1_name=request_id|p1_desc=A valid HTTP request key | |||
|p2_type=integer|p2_name=status|p2_desc=[http://en.wikipedia.org/wiki/List_of_HTTP_status_codes HTTP_Status] (200, 400, 404, etc) | |||
|p3_type=string|p3_name=body|p3_desc=Contents of the response. | |||
|func_desc=Responds to {{LSLP|request_id}} with {{LSLP|status}} and {{LSLP|body}}. | |||
|func_footer=The response need not be made inside the [[http_request]] [[event]] but if it does not happen in a timely fashion the request will time out (within 25 seconds). | |||
|caveats=none | |||
}} | |||
{{LSL Function/Head | |||
|func_id=344|func_sleep=0.0|func_energy=10.0 | |||
|func=llGetFreeURLs | |||
|return_type=integer|return_text=that is the number of available URLs. | |||
|caveats=none | |||
}} | |||
{{LSL Function/Head | |||
|func_id=349|func_sleep=0.0|func_energy=10.0 | |||
|func=llGetHTTPHeader | |||
|p1_type=key|p1_name=request_id|p1_desc=A valid HTTP request key | |||
|p2_type=string|p2_name=header|p2_desc=Lower case header value name | |||
|return_type=string|return_text=that is the value for {{LSLP|header}} for {{LSLP|request_id}}. | |||
|func_footer=Returns an empty [[string]] if the {{LSLP|header}} is not found or if the headers can no longer be accessed. Headers can only be accessed before [[llHTTPResponse]] is called and with-in the first 30 seconds after the [[http_request]] [[event]] is queued. | |||
====Generated Headers==== | |||
These headers are automatically generated by the simulator, they were not actually sent by the requesting client. They supply information about the request to make parsing easier. | |||
Sample URL: [https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/foo/bar?arg=gra {{HoverTextStyle|style=color:green;|<nowiki>https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322</nowiki>|2={{String|x-script-url}} = {{String|https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322}}}}{{HoverTextStyle|style=color:blue;|/foo/bar|2={{String|x-path-info}} = {{String|/foo/bar}}}}?{{HoverTextStyle|style=color:red;|1=arg=gra|2={{String|x-query-string}} = {{String|1=arg=gra}}}}] | |||
{{{!}} class="lltable" border="1" | |||
! header | |||
! description | |||
! example | |||
{{!}}- | |||
{{!}} style="white-space: nowrap;" {{!}} "x-script-url" | |||
{{!}} The base url, as originally received from [[llRequestURL]]/[[llRequestSecureURL]] | |||
{{!}} <font color="green"><nowiki>https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322</nowiki></font> | |||
{{!}}- | |||
{{!}} style="white-space: nowrap;" {{!}} "x-path-info" | |||
{{!}} Any trailing path information from the requested url | |||
{{!}} <font color="blue">/foo/bar</font> | |||
{{!}}- | |||
{{!}} style="white-space: nowrap;" {{!}} "x-query-string" | |||
{{!}} Any query arguments, the text past the first "?" in the url | |||
{{!}} <font color="red">arg=gra</font> | |||
{{!}}- | |||
{{!}} style="white-space: nowrap;" {{!}} "x-remote-ip" | |||
{{!}} IP address of the host that made the request | |||
{{!}} | |||
{{!}}} | |||
====Common Headers==== | |||
{{{!}} class="lltable" border="1" | |||
! header | |||
! description | |||
! example | |||
{{!}}- | |||
{{!}} style="white-space: nowrap;" {{!}} "user-agent" | |||
{{!}} The user-agent header as reported by the requester | |||
{{!}} | |||
{{!}}} | |||
====[[llHTTPRequest]] Headers==== | |||
{{LSL_Constants/HTTP_Headers|lower-case=*}} | |||
|caveats=none | |||
}} | |||
= URL Lifetime Limitations = | |||
* URLs are '''temporary'''! | * URLs are '''temporary'''! | ||
* URLs will be lost in the following cases, all detectable by the script events listed with them. | * URLs will be lost in the following cases, all detectable by the script events listed with them. | ||
** On object derez/rez: [[on_rez]] | ** On object derez/rez: [[on_rez]] | ||
** On script save/reset: ''[[default]] [[state_entry]] | ** On script save/reset: ''[[default]] [[state_entry]] (trickier in multi-state [[Script|LSL scripts]]) | ||
** On region cross or TP(attachments): [[changed]] | ** On region cross or TP(attachments): [[changed]] {{LSLGC|Events|event}}, [[CHANGED_REGION]] and [[CHANGED_TELEPORT]]. Testing the latter event, it has been found that teleports within a region DO NOT cause a URL to be lost, therefore you do not need to request a new URL on [[CHANGED_TELEPORT]], because [[CHANGED_REGION]] will handle a teleport to a different region. If you choose to request a URL after a teleport, it is recommended to release the old URL to be sure you don't have too many used. (Stone Tremont Aug 8th 2010) | ||
** On region restart: [[changed]] | ** On region restart: [[changed]] [[event]], flag [[CHANGED_REGION_START]] | ||
* When urls are 'lost' it means that all public urls for that script are gone, new ones will need to be requested and the new urls will | * When urls are 'lost' it means that all public urls for that script are gone, new ones will need to be requested and the new urls will '''not''' resemble the old ones. | ||
* Maintaining persistent URLs will require building or using an external service similar to how [http://en.wikipedia.org/wiki/Dynamic_DNS Dynamic DNS] services work for tying domain names to dynamic IP addresses. | * Maintaining persistent URLs will require building or using an external service similar to how [http://en.wikipedia.org/wiki/Dynamic_DNS Dynamic DNS] services work for tying domain names to dynamic IP addresses. | ||
Contributed HTTP-in URL mapping implementations and services: | Contributed HTTP-in URL mapping implementations and services: | ||
* A Dynamic DNS service running on Google App Engine (contributed as an example) can be found in the forums | * A Dynamic DNS service running on Google App Engine (contributed as an example) can be found in the forums [http://wiki.secondlife.com/wiki/User:Darien_Caldwell/HTTP-DNS here]. | ||
* Yet another one, running on GAE, with password protected and private domains. http://wiki.secondlife.com/wiki/Public_Object_DNS | |||
* The [http://www.silverday.net/sqndns SilverDay ObjectDNS] is an easy to use dns-mapping-service with many configurable options (password protection, write protection, etc.) and an optional web-interface. The [[Script|LSL scripts]] are available here on the wiki (LSL-Script Library/[[Silverday ObjectDNS]]). | |||
* Yet another one, running on GAE, with password protected and private domains. | |||
* | |||
= Resource Limitations = | |||
* There are a limited number of URLs available in each region, split by land ownership exactly like prim limits. | * There are a limited number of URLs available in each [[region]], split by land ownership exactly like prim limits. | ||
** Use [[llGetFreeURLs]] to get the exact number of available URLs for the script. | ** Use [[llGetFreeURLs]] to get the exact number of available URLs for the script. | ||
** The number of allowed URLs is the same as the number of allowed prims on the parcel the object is over. | ** The number of allowed URLs is the same as the number of allowed [[prim|prims]] on the [[Land#Parcel|parcel]] the [[object]] is over. | ||
**: ''Object owner does not matter, all objects over a parcel will use the resource pool for that parcel.'' | **: ''Object owner does not matter, all objects over a [[Land#Parcel|parcel]] will use the resource pool for that [[Land#Parcel|parcel]].'' | ||
**: ''Like prims, all the parcels owned by the same owner and in the same region share the same pool of resources.'' | **: ''Like [[prim|prims]], all the [[Land#Parcel|parcels]] owned by the same owner and in the same [[region]] share the same pool of resources.'' | ||
**: ''If you have two parcels in a region that each support 100 URLs, then you could use all 200 in object(s) on a single parcel.'' | **: ''If you have two [[Land#Parcel|parcels]] in a [[region]] that each support 100 URLs, then you could use all 200 in object(s) on a single [[Land#Parcel|parcel]].'' | ||
** The region's object bonus factor does not apply to available URLs. | ** The [[region]]'s [[object]] bonus factor does not apply to available URLs. | ||
**: ''If a parcel has a max of 300 prims in a region with a 2x bonus factor there will only be 150 urls allowed.'' | **: ''If a [[Land#Parcel|parcel]] has a max of 300 [[prim|prims]] in a [[region]] with a 2x bonus factor there will only be 150 urls allowed.'' | ||
* Each resident has their own unique pool of available URLs with a max of 38 URLs per resident. | * Each resident has their own unique pool of available URLs with a max of 38 URLs per resident. | ||
** This is 1 per attachment point, but all 38 could be used by a single attachment for example. | ** This is 1 per attachment point, but all 38 could be used by a single attachment for example. | ||
* Vehicles are special and lazily moved to resident pools by the following logic: | * Vehicles are special and lazily moved to resident pools by the following logic: | ||
** Any object that has a resident sitting on it is a 'vehicle' | ** Any [[object]] that has a resident sitting on it is a 'vehicle' | ||
** Vehicles will use the url resources from the parcel they are over until the cross a parcel border. | ** Vehicles will use the url resources from the [[Land#Parcel|parcel]] they are over until the cross a [[Land#Parcel|parcel]] border. | ||
**: ''Specifically this prevents anyone from breaking your vending machine by sitting on it and making it a 'vehicle'.'' | **: ''Specifically this prevents anyone from breaking your vending machine by sitting on it and making it a 'vehicle'.'' | ||
** When any object using URL resources with a resident sitting on it crosses a parcel boundary the resources will switch to the first sitting resident with enough resources. | ** When any [[object]] using URL resources with a resident sitting on it crosses a [[Land#Parcel|parcel]] boundary the resources will switch to the first sitting resident with enough resources. If no sitting agents have enough resources then the resources from the [[Land#Parcel|parcel]] being moved onto will be used. If even then there are not enough resources to use then the vehicle will be blocked from moving. | ||
**: ''In short we do everything we can to find a pool to host the resources needed by the vehicle, but will block movement if we can't.'' | **: ''In short we do everything we can to find a pool to host the resources needed by the vehicle, but will block movement if we can't.'' | ||
* Parcel Sale: When a parcel is sold such that it changes the total available URLs in the region for either resident (seller or buyer) such that more URLs are being used than are available some objects will be returned. | * Parcel Sale: When a [[Land#Parcel|parcel]] is sold such that it changes the total available URLs in the [[region]] for either resident (seller or buyer) such that more URLs are being used than are available some objects will be returned. | ||
** The objects returned will be from youngest object to oldest object of those using URLs in each category in order of object category: Temporary, Other, Group, Owner, Selected/Sat upon. | ** The objects returned will be from youngest [[object]] to oldest [[object]] of those using URLs in each category in order of [[object]] category: Temporary, Other, Group, Owner, Selected/Sat upon. | ||
**: ''The '''only''' time objects are possibly returned is when parcels change owner, and only if more resources are being used than allowed.'' | **: ''The '''only''' time objects are possibly returned is when [[Land#Parcel|parcels]] change owner, and only if more resources are being used than allowed.'' | ||
**: ''We return youngest temporary objects before older temporary objects before younger 'other' (owned by non-group, non-parcel-owner) objects etc.'' | **: ''We return youngest temporary objects before older temporary objects before younger 'other' (owned by non-group, non-[[Land#Parcel|parcel]]-owner) objects etc.'' | ||
= Other Limitations = | |||
* Size of the body of the | * Size of the body of requests on the '''[[:Category:LSL HTTP#Understanding_LSL_HTTP_Communications | Incoming pipeline]]''' will be [[limit]]ed to 2k [[bytes]], and cannot currently be changed. | ||
* Size of headers of requests will be limited to 255 bytes | * Size of headers of requests will be limited to 255 bytes per header, not total. | ||
* The size of responses to requests is not currently limited, but this is subject to review during testing. | * The size of responses to requests is not currently limited, but this is subject to review during testing. | ||
* | * By default the content type of the returned data is always <code>"text/plain; charset=utf-8"</code>, this however can be changed via [[llSetContentType]] for all subsequent responses via [[llHTTPResponse]]. | ||
* There is a cap of 64 in flight requests per script. This is based on the maximum number of pending [[event|events]] in LSL. After hitting the 64 request limit, the simulator cap server returns <code>{{String|503 Service Unavailable}}</code> to the inbound request. | |||
* There is a cap of 64 in flight requests per script. This is based on the maximum number of pending events in LSL. | * ''We may throttle the rate we accept hits at the CAP server level as well. This is possible, but has not yet been decided.'' | ||
* ''We may throttle the rate we accept hits at the CAP server level as well. | * HTML can be used to in-client browser, including media on a prim, with some restrictions. See [[llSetContentType]] and [[CONTENT_TYPE_HTML]] for further details. | ||
* HTML | * If making a parser, remember that you should probably restrict access to only Linden Lab HTML URLs as to not have your bandwith stolen. See [[Simulator_IP_Addresses]] for details. | ||
* It is important to note that when appending a query string to a cap URL there MUST be a trailing slash between the cap guid and the query string token | * It is important to note that when appending a query string to a cap URL there '''MUST''' be a trailing slash between the cap guid and the query string token <code>"?"</code>. For example: [https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322?arg=gra {{HoverTextStyle|style=color:green;|<nowiki>https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322</nowiki>|2={{String|x-script-url}} = {{String|https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322}}}}?{{HoverTextStyle|style=color:red;|1=arg=gra|2={{String|x-query-string}} = {{String|1=arg=gra}}}}] will return a 500 HTTP status {{Wikipedia|List_of_HTTP_status_codes#5xx_Server_Error|Server Error code}}, but [https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/?arg=gra {{HoverTextStyle|style=color:green;|<nowiki>https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322</nowiki>|2={{String|x-script-url}} = {{String|https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322}}}}{{HoverTextStyle|style=color:blue;|/|2={{String|x-path-info}} = {{String|/}}}}?{{HoverTextStyle|style=color:red;|1=arg=gra|2={{String|x-query-string}} = {{String|1=arg=gra}}}}] will succeed. | ||
= Links = | |||
* [[LSL_http_server/examples | Script Examples]] | * [[LSL_http_server/examples | Script Examples]] | ||
* [[LSL_http_server/design | Design Document]] | * [[LSL_http_server/design | Design Document]] |
Latest revision as of 01:54, 16 November 2022
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Introduction
This is the counterpart to llHTTPRequest. While llHTTPRequest enables LSL scripts to request data from HTTP-accessible sources, HTTP-in enables outside sources to request data from LSL scripts in Second Life. The key difference is that llHTTPRequest exchanges data when the script in SL wants; HTTP-in allows outside sources to determine when they need to communicate with LSL scripts in SL.
Prior to HTTP-in, similar functionality could be achieved by polling with llHTTPRequest, llEmail and XML-RPC. All three are cumbersome and the latter two have serious scalability bottlenecks.
It is important to note that LSL HTTP servers cannot use llSetContentType with CONTENT_TYPE_HTML for an llHTTPResponse except in very limited circumstances. See Other Limitations for details.
This section forms the Incoming HTTP pipeline.
Uses
- Easily get data from LSL scripts to outside viewers, LSL scripts or servers.
- Web front end for a visitor counter or other statistics accumulator.
- Easily get data into LSL scripts from outside viewers, LSL scripts or servers.
- A store with a web front end that communicates to an in-world object to exchange L$ and inventory items.
- Inworld game for which an external program handles the primary game logic that needs to manipulate inworld items.
- HUD UI when used with llSetContentType. See HTML HUD Demo.
Gory Technical Details follow. Or jump straight to the Script Examples.
Script API
Events
- Event triggered when an URL is hit:
- id is unique to this request
- Supported methods are
"GET"
,"POST"
,"PUT"
,"DELETE"
- body: The body of the request.
- Event also triggered with response to llRequestURL and llRequestSecureURL
- id matches the key returned by llRequestURL or llRequestSecureURL
- method == URL_REQUEST_GRANTED for success, URL_REQUEST_DENIED for failure to get an URL
- body is the public URL. If unable to get a public URL body will be empty.
- CHANGED_REGION_START: New changed event triggered on region startup.
- CHANGED_REGION: New changed event triggered when crossing regions or teleporting. Please read CHANGED_REGION for more info.
- CHANGED_TELEPORT: New changed event triggered when the avatar teleports. Please read CHANGED_TELEPORT for more info.
Functions
llRequestURL
Function: key llRequestURL( );0.0 | Forced Delay |
10.0 | Energy |
Requests one HTTP:// url for use by the script. The http_request event is triggered with the result of the request. HTTP-in uses port 12046.
Returns a key that is the handle used for identifying the result in the http_request event.
llRequestSecureURL
Function: key llRequestSecureURL( );0.0 | Forced Delay |
10.0 | Energy |
Requests one HTTPS:// (SSL) url for use by the script. The http_request event is triggered with the result of the request. HTTPS-in uses port 12043.
Returns a key that is the handle used for identifying the result in the http_request event.
llReleaseURL
Function: llReleaseURL( string url );0.0 | Forced Delay |
10.0 | Energy |
Releases the specified URL, it will no longer be usable.
• string | url | – | URL to release |
llHTTPResponse
Function: llHTTPResponse( key request_id, integer status, string body );0.0 | Forced Delay |
10.0 | Energy |
Responds to request_id with status and body.
• key | request_id | – | A valid HTTP request key | |
• integer | status | – | HTTP_Status (200, 400, 404, etc) | |
• string | body | – | Contents of the response. |
The response need not be made inside the http_request event but if it does not happen in a timely fashion the request will time out (within 25 seconds).
llGetFreeURLs
Function: integer llGetFreeURLs( );0.0 | Forced Delay |
10.0 | Energy |
Returns an integer that is the number of available URLs.
llGetHTTPHeader
Function: string llGetHTTPHeader( key request_id, string header );0.0 | Forced Delay |
10.0 | Energy |
Returns a string that is the value for header for request_id.
• key | request_id | – | A valid HTTP request keyA valid HTTP request key | |
• string | header | – | Lower case header value name |
Returns an empty string if the header is not found or if the headers can no longer be accessed. Headers can only be accessed before llHTTPResponse is called and with-in the first 30 seconds after the http_request event is queued.
Generated Headers
These headers are automatically generated by the simulator, they were not actually sent by the requesting client. They supply information about the request to make parsing easier.
Sample URL: https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/foo/bar?arg=gra
header | description | example |
---|---|---|
"x-script-url" | The base url, as originally received from llRequestURL/llRequestSecureURL | https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322 |
"x-path-info" | Any trailing path information from the requested url | /foo/bar |
"x-query-string" | Any query arguments, the text past the first "?" in the url | arg=gra |
"x-remote-ip" | IP address of the host that made the request |
Common Headers
header | description | example |
---|---|---|
"user-agent" | The user-agent header as reported by the requester |
llHTTPRequest Headers
Header | Description | Example data |
---|---|---|
connection | Connection options | close |
cache-control | Maximum response age accepted. | max-age=259200 |
x-forwarded-for | Used to show the IP address connected to through proxies. | 127.0.0.1 |
via | Shows the recipients and protocols used between the User Agent and the server. | 1.1 sim10115.agni.lindenlab.com:3128 (squid/2.7.STABLE9) |
content-length | The size of the entity-body, in decimal number of octets. | 17 |
pragma | The message should be forwarded to the server, even if it has a cached version of the data. | no-cache |
x-secondlife-shard | The environment the object is in. "Production" is the main grid and "Testing" is the preview grid | Production |
x-secondlife-region | The name of the region the object is in, along with the global coordinates of the region's south-west corner | Jin Ho (264448, 233984) |
x-secondlife-owner-name | Legacy name of the owner of the object | Zeb Wyler |
x-secondlife-owner-key | UUID of the owner of the object | 01234567-89ab-cdef-0123-456789abcdef |
x-secondlife-object-name | The name of the object containing the script | Object |
x-secondlife-object-key | The key of the object containing the script | 01234567-89ab-cdef-0123-456789abcdef |
x-secondlife-local-velocity | The velocity of the object | 0.000000, 0.000000, 0.000000 |
x-secondlife-local-rotation | The rotation of the object containing the script | 0.000000, 0.000000, 0.000000, 1.000000 |
x-secondlife-local-position | The position of the object within the region | (173.009827, 75.551231, 60.950001) |
user-agent | The user-agent header sent by LSL Scripts. Contains Server version. | Second Life LSL/16.05.24.315768 (http://secondlife.com) |
content-type | The media type of the entity body. | text/plain; charset=utf-8 |
accept-charset | Acceptable character sets from the server. Q being the quality expected when sending the different character sets. | utf-8;q=1.0, *;q=0.5 |
accept | Media types the server will accept. | text/*, application/xhtml+xml, application/atom+xml, application/json, application/xml, application/llsd+xml, application/x-javascript, application/javascript, application/x-www-form-urlencoded, application/rss+xml |
accept-encoding | Acceptable content encodings for the server. | deflate, gzip |
host | The internet host being requested. | secondlife.com |
|
URL Lifetime Limitations
- URLs are temporary!
- URLs will be lost in the following cases, all detectable by the script events listed with them.
- On object derez/rez: on_rez
- On script save/reset: default state_entry (trickier in multi-state LSL scripts)
- On region cross or TP(attachments): changed event, CHANGED_REGION and CHANGED_TELEPORT. Testing the latter event, it has been found that teleports within a region DO NOT cause a URL to be lost, therefore you do not need to request a new URL on CHANGED_TELEPORT, because CHANGED_REGION will handle a teleport to a different region. If you choose to request a URL after a teleport, it is recommended to release the old URL to be sure you don't have too many used. (Stone Tremont Aug 8th 2010)
- On region restart: changed event, flag CHANGED_REGION_START
- When urls are 'lost' it means that all public urls for that script are gone, new ones will need to be requested and the new urls will not resemble the old ones.
- Maintaining persistent URLs will require building or using an external service similar to how Dynamic DNS services work for tying domain names to dynamic IP addresses.
Contributed HTTP-in URL mapping implementations and services:
- A Dynamic DNS service running on Google App Engine (contributed as an example) can be found in the forums here.
- Yet another one, running on GAE, with password protected and private domains. http://wiki.secondlife.com/wiki/Public_Object_DNS
- The SilverDay ObjectDNS is an easy to use dns-mapping-service with many configurable options (password protection, write protection, etc.) and an optional web-interface. The LSL scripts are available here on the wiki (LSL-Script Library/Silverday ObjectDNS).
Resource Limitations
- There are a limited number of URLs available in each region, split by land ownership exactly like prim limits.
- Use llGetFreeURLs to get the exact number of available URLs for the script.
- The number of allowed URLs is the same as the number of allowed prims on the parcel the object is over.
- Object owner does not matter, all objects over a parcel will use the resource pool for that parcel.
- Like prims, all the parcels owned by the same owner and in the same region share the same pool of resources.
- If you have two parcels in a region that each support 100 URLs, then you could use all 200 in object(s) on a single parcel.
- The region's object bonus factor does not apply to available URLs.
- Each resident has their own unique pool of available URLs with a max of 38 URLs per resident.
- This is 1 per attachment point, but all 38 could be used by a single attachment for example.
- Vehicles are special and lazily moved to resident pools by the following logic:
- Any object that has a resident sitting on it is a 'vehicle'
- Vehicles will use the url resources from the parcel they are over until the cross a parcel border.
- Specifically this prevents anyone from breaking your vending machine by sitting on it and making it a 'vehicle'.
- When any object using URL resources with a resident sitting on it crosses a parcel boundary the resources will switch to the first sitting resident with enough resources. If no sitting agents have enough resources then the resources from the parcel being moved onto will be used. If even then there are not enough resources to use then the vehicle will be blocked from moving.
- In short we do everything we can to find a pool to host the resources needed by the vehicle, but will block movement if we can't.
- Parcel Sale: When a parcel is sold such that it changes the total available URLs in the region for either resident (seller or buyer) such that more URLs are being used than are available some objects will be returned.
Other Limitations
- Size of the body of requests on the Incoming pipeline will be limited to 2k bytes, and cannot currently be changed.
- Size of headers of requests will be limited to 255 bytes per header, not total.
- The size of responses to requests is not currently limited, but this is subject to review during testing.
- By default the content type of the returned data is always
"text/plain; charset=utf-8"
, this however can be changed via llSetContentType for all subsequent responses via llHTTPResponse. - There is a cap of 64 in flight requests per script. This is based on the maximum number of pending events in LSL. After hitting the 64 request limit, the simulator cap server returns
"503 Service Unavailable"
to the inbound request. - We may throttle the rate we accept hits at the CAP server level as well. This is possible, but has not yet been decided.
- HTML can be used to in-client browser, including media on a prim, with some restrictions. See llSetContentType and CONTENT_TYPE_HTML for further details.
- If making a parser, remember that you should probably restrict access to only Linden Lab HTML URLs as to not have your bandwith stolen. See Simulator_IP_Addresses for details.
- It is important to note that when appending a query string to a cap URL there MUST be a trailing slash between the cap guid and the query string token
"?"
. For example: https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322?arg=gra will return a 500 HTTP status Server Error code, but https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/?arg=gra will succeed.
Links
- Script Examples
- Design Document
- Design Jira:SVC-1086