* added basic cookie support:
- any cookie received from the remote server will now be part of the result object returned by getUrl() - added methods setCookie(), getCookie() and getCookies() for adding and retrieving cookies * added JsDoc compatible inline documentation (due to a bug in JsDoc the static methods setProxy and getProxy don't show up in the generated docs) * switched to using app.logger for log output
This commit is contained in:
parent
585666e577
commit
b11fce933f
1 changed files with 372 additions and 48 deletions
396
helma/Http.js
396
helma/Http.js
|
@ -9,21 +9,41 @@
|
|||
* Copyright 1998-2006 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile: Http.js,v $
|
||||
* $Author: czv $
|
||||
* $Revision: 1.2 $
|
||||
* $Date: 2006/04/24 07:02:17 $
|
||||
* $Author: hannes $
|
||||
* $Revision: 1.3 $
|
||||
* $Date: 2006/11/21 10:42:25 $
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @fileoverview Fields and methods of the helma.Http class.
|
||||
*/
|
||||
|
||||
// take care of any dependencies
|
||||
app.addRepository('modules/core/Date.js');
|
||||
|
||||
|
||||
/**
|
||||
* Define the global namespace if not existing
|
||||
*/
|
||||
if (!global.helma) {
|
||||
global.helma = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of helma.Http
|
||||
* @class This class provides functionality to programatically issue
|
||||
* an Http request based on java.net.HttpUrlConnection.
|
||||
* By default the request will use method <code>GET</code>.
|
||||
* @returns A newly created helma.Http instance
|
||||
* @constructor
|
||||
*/
|
||||
helma.Http = function() {
|
||||
var proxy = null;
|
||||
var content = "";
|
||||
var userAgent = "Helma Http Client";
|
||||
var method = "GET";
|
||||
var cookies = null;
|
||||
var credentials = null;
|
||||
var followRedirects = true;
|
||||
var binaryMode = false;
|
||||
|
@ -33,18 +53,22 @@ helma.Http = function() {
|
|||
"socket": 0
|
||||
};
|
||||
|
||||
/** @private */
|
||||
var setTimeout = function(type, value) {
|
||||
var v = java.lang.System.getProperty("java.specification.version");
|
||||
if (parseFloat(v, 10) >= 1.5) {
|
||||
timeout[type] = value;
|
||||
} else {
|
||||
app.log("[Helma Http Client] WARNING: timeouts can only be set with Java Runtime version >= 1.5");
|
||||
app.logger.warn("helma.Http: Timeouts can only be set with Java Runtime version >= 1.5");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the proxy host and port for later use
|
||||
* Sets the proxy host and port for later use. The argument must
|
||||
* be in <code>host:port</code> format (eg. "proxy.example.com:3128").
|
||||
* @param {String} proxyString The proxy to use for this request
|
||||
* @see #getProxy
|
||||
*/
|
||||
this.setProxy = function(proxyString) {
|
||||
var idx = proxyString.indexOf(":");
|
||||
|
@ -58,17 +82,20 @@ helma.Http = function() {
|
|||
// the pre jdk1.5 way: set the system properties
|
||||
var sys = java.lang.System.getProperties();
|
||||
if (host) {
|
||||
app.log("[Helma Http Client] WARNING: setting system http proxy to " + host + ":" + port);
|
||||
app.logger.warn("[Helma Http Client] WARNING: setting system http proxy to " + host + ":" + port);
|
||||
sys.put("http.proxySet", "true");
|
||||
sys.put("http.proxyHost", host);
|
||||
sys.put("http.proxyPort", port);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* returns the proxy in "host:port" format
|
||||
* Returns the proxy in <code>host:port</code> format
|
||||
* @return The proxy defined for this request
|
||||
* @type String
|
||||
* @see #setProxy
|
||||
*/
|
||||
this.getProxy = function() {
|
||||
if (proxy != null) {
|
||||
|
@ -81,15 +108,24 @@ helma.Http = function() {
|
|||
};
|
||||
|
||||
/**
|
||||
* sets the credentials for basic http authentication
|
||||
* Sets the credentials for basic http authentication
|
||||
* @param {String} username The username
|
||||
* @param {String} password The password
|
||||
*/
|
||||
this.setCredentials = function(username, password) {
|
||||
var str = new java.lang.String(username + ":" + password);
|
||||
credentials = (new Packages.sun.misc.BASE64Encoder()).encode(str.getBytes());
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content to send to the remote server within this request.
|
||||
* @param {String|Object} stringOrObject The content of the request, which
|
||||
* can be either a string or an object. In the latter case all properties
|
||||
* and their values are concatenated into a single string.
|
||||
*/
|
||||
this.setContent = function(stringOrObject) {
|
||||
if (stringOrObject != null) {
|
||||
if (stringOrObject.constructor == Object) {
|
||||
res.push();
|
||||
var value;
|
||||
|
@ -102,82 +138,226 @@ helma.Http = function() {
|
|||
}
|
||||
content = res.pop();
|
||||
content = content.substring(0, content.length-1);
|
||||
} else
|
||||
} else {
|
||||
content = stringOrObject.toString();
|
||||
}
|
||||
} else {
|
||||
content = null;
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* getter/setter for method
|
||||
* Sets the request method to use.
|
||||
* @param {String} m The method to use (<code>GET</code>, <code>POST</code> ...)
|
||||
* @see #getMethod
|
||||
*/
|
||||
this.setMethod = function(m) {
|
||||
method = m;
|
||||
return true;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the currently defined request method.
|
||||
* @returns The method used
|
||||
* @type String
|
||||
* @see #setMethod
|
||||
*/
|
||||
this.getMethod = function() {
|
||||
return method;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a single HTTP request header field
|
||||
* @param {String} name The name of the header field
|
||||
* @param {String} value The value of the header field
|
||||
* @see #getHeader
|
||||
*/
|
||||
this.setHeader = function(name, value) {
|
||||
headers[name] = value;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value of the request header field with the given name
|
||||
* @param {String} name The name of the request header field
|
||||
* @returns The value of the request header field
|
||||
* @type String
|
||||
* @see #setHeader
|
||||
*/
|
||||
this.getHeader = function(name) {
|
||||
return headers[name];
|
||||
};
|
||||
|
||||
/**
|
||||
* getter/setter for timeouts
|
||||
* Adds a cookie with the name and value passed as arguments
|
||||
* to the list of cookies to send to the remote server.
|
||||
* @param {String} name The name of the cookie
|
||||
* @param {String} value The value of the cookie
|
||||
* @see #getCookie
|
||||
* @see #getCookies
|
||||
*/
|
||||
this.setCookie = function(name, value) {
|
||||
if (name != null && value != null) {
|
||||
// store the cookie in the cookies map
|
||||
if (!cookies) {
|
||||
cookies = {};
|
||||
}
|
||||
cookies[name] = new helma.Http.Cookie(name, value);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value of the cookie with the given name
|
||||
* @param {String} name The name of the cookie
|
||||
* @returns The value of the cookie
|
||||
* @type String
|
||||
* @see #setCookie
|
||||
*/
|
||||
this.getCookie = function(name) {
|
||||
return (cookies != null) ? cookies[name] : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all cookies set for this client
|
||||
* @return An object containing all cookies, where the property
|
||||
* name is the name of the cookie, and the value is the cookie value
|
||||
* @see #setCookie
|
||||
*/
|
||||
this.getCookies = function() {
|
||||
return cookies;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the connection timeout to the amount of milliseconds
|
||||
* passed as argument
|
||||
* @param {Number} timeout The connection timeout in milliseconds
|
||||
* @see #getTimeout
|
||||
*/
|
||||
this.setTimeout = function(timeout) {
|
||||
setTimeout("connect", timeout);
|
||||
return true;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the read timeout (the maximum time a request may take after
|
||||
* the connection has been successfully established) to the amount of
|
||||
* milliseconds passed as argument.
|
||||
* @param {Number} timeout The read timeout in milliseconds
|
||||
* @see #getReadTimeout
|
||||
*/
|
||||
this.setReadTimeout = function(timeout) {
|
||||
setTimeout("socket", timeout);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the connection timeout
|
||||
* @returns The connection timeout in milliseconds
|
||||
* @type Number
|
||||
* @see #setTimeout
|
||||
*/
|
||||
this.getTimeout = function() {
|
||||
return timeout.connect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the read timeout (the maximum time a request may take after
|
||||
* the connection has been successfully established).
|
||||
* @returns The read timeout in milliseconds
|
||||
* @type Number
|
||||
* @see #setReadTimeout
|
||||
*/
|
||||
this.getReadTimeout = function() {
|
||||
return timeout.socket;
|
||||
};
|
||||
|
||||
/**
|
||||
* getter/setter for following redirects
|
||||
* Enables or disables following redirects
|
||||
* @param {Boolean} value If false this client won't follow redirects (the default is
|
||||
* to follow them)
|
||||
* @see #getFollowRedirects
|
||||
*/
|
||||
this.setFollowRedirects = function(value) {
|
||||
followRedirects = value;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the client follows redirects
|
||||
* @returns True if the client follows redirects, false otherwise.
|
||||
* @see #setFollowRedirects
|
||||
*/
|
||||
this.getFollowRedirects = function() {
|
||||
return followRedirects;
|
||||
};
|
||||
|
||||
/**
|
||||
* getter/setter for user agent string
|
||||
* Sets the HTTP "User-Agent" header field to the string passed as argument
|
||||
* @param {String} agent The string to use as value of the
|
||||
* "User-Agent" header field (defaults to "Helma Http Client")
|
||||
* @see #getUserAgent
|
||||
*/
|
||||
this.setUserAgent = function(agent) {
|
||||
userAgent = agent;
|
||||
return true;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value of the HTTP "User-Agent" header field
|
||||
* @returns The value of the field
|
||||
* @type String
|
||||
* @see #setUserAgent
|
||||
*/
|
||||
this.getUserAgent = function() {
|
||||
return userAgent;
|
||||
};
|
||||
|
||||
/**
|
||||
* switches content text encoding on/off
|
||||
* Switches content text encoding on or off. Depending on this
|
||||
* the content received from the remote server will be either a
|
||||
* string or a byte array.
|
||||
* @param {Boolean} mode If true binary mode is activated
|
||||
* @see #getBinaryMode
|
||||
*/
|
||||
this.setBinaryMode = function(mode) {
|
||||
binaryMode = mode;
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the currently defined binary mode of this client
|
||||
* @returns The binary mode of this client
|
||||
* @type Boolean
|
||||
* @see #setBinaryMode
|
||||
*/
|
||||
this.getBinaryMode = function() {
|
||||
return binaryMode;
|
||||
};
|
||||
|
||||
/**
|
||||
* executes a http request
|
||||
* Executes a http request
|
||||
* @param {String} url The url to request
|
||||
* @param {Date|String} opt If this argument is a string, it is used
|
||||
* as value for the "If-None-Match" request header field. If it is a
|
||||
* Date instance it is used as "IfModifiedSince" condition for this request.
|
||||
* @return A result object containing the following properties:
|
||||
* <ul>
|
||||
* <li><code>url</code>: (String) The Url of the request</li>
|
||||
* <li><code>location</code>: (String) The value of the location header field</li>
|
||||
* <li><code>code</code>: (Number) The HTTP response code</li>
|
||||
* <li><code>message</code>: (String) An optional HTTP response message</li>
|
||||
* <li><code>length</code>: (Number) The content length of the response</li>
|
||||
* <li><code>type</code>: (String) The mimetype of the response</li>
|
||||
* <li><code>encoding</code>: (String) An optional encoding to use with the response</li>
|
||||
* <li><code>lastModified</code>: (String) The value of the lastModified response header field</li>
|
||||
* <li><code>eTag</code>: (String) The eTag as received from the remote server</li>
|
||||
* <li><code>cookie</code>: (helma.Http.Cookie) An object containing the cookie parameters, if the remote
|
||||
server has set the "Set-Cookie" header field</li>
|
||||
* <li><code>content</code>: (String|ByteArray) The response received from the server. Can be either
|
||||
a string or a byte array (see #setBinaryMode)</li>
|
||||
* </ul>
|
||||
*/
|
||||
this.getUrl = function(url, opt) {
|
||||
if (typeof url == "string") {
|
||||
|
@ -202,16 +382,24 @@ helma.Http = function() {
|
|||
if (credentials != null) {
|
||||
conn.setRequestProperty("Authorization", "Basic " + credentials);
|
||||
}
|
||||
// set timeouts
|
||||
if (parseFloat(java.lang.System.getProperty("java.specification.version"), 10) >= 1.5) {
|
||||
conn.setConnectTimeout(timeout.connect);
|
||||
conn.setReadTimeout(timeout.socket);
|
||||
} else {
|
||||
app.debug("WARNING: timeouts can only be set due to Java version < 1.5");
|
||||
}
|
||||
|
||||
for (var i in headers)
|
||||
// set header fields
|
||||
for (var i in headers) {
|
||||
conn.setRequestProperty(i, headers[i]);
|
||||
|
||||
}
|
||||
// set cookies
|
||||
if (cookies != null) {
|
||||
var arr = [];
|
||||
for (var i in cookies) {
|
||||
arr[arr.length] = cookies[i].getFieldValue();
|
||||
}
|
||||
conn.setRequestProperty("Cookie", arr.join(";"));
|
||||
}
|
||||
// set content
|
||||
if (content) {
|
||||
conn.setRequestProperty("Content-Length", content.length);
|
||||
conn.setDoOutput(true);
|
||||
|
@ -231,6 +419,7 @@ helma.Http = function() {
|
|||
encoding: conn.getContentEncoding(),
|
||||
lastModified: null,
|
||||
eTag: null,
|
||||
cookie: helma.Http.Cookie.parse(conn.getHeaderField("Set-Cookie")),
|
||||
content: null
|
||||
}
|
||||
var lastmod = conn.getLastModified();
|
||||
|
@ -260,6 +449,7 @@ helma.Http = function() {
|
|||
return result;
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
this.toString = function() {
|
||||
return "[Helma Http Client]";
|
||||
};
|
||||
|
@ -272,9 +462,11 @@ helma.Http = function() {
|
|||
|
||||
|
||||
/**
|
||||
* removes trailing slash from and evaluates a url
|
||||
* @param String the url or uri string
|
||||
* @return Object the result with error and result properties
|
||||
* Evaluates the url passed as argument.
|
||||
* @param {String} url The url or uri string to evaluate
|
||||
* @returns If the argument is a valid url, this method returns
|
||||
* a new instance of java.net.URL, otherwise it returns null.
|
||||
* @type java.net.URL
|
||||
*/
|
||||
helma.Http.evalUrl = function(url) {
|
||||
try {
|
||||
|
@ -286,7 +478,16 @@ helma.Http.evalUrl = function(url) {
|
|||
|
||||
|
||||
/**
|
||||
* set global http proxy
|
||||
* Sets the global http proxy setting. If no proxy definition
|
||||
* is passed to this method, any existing proxy setting is
|
||||
* cleared. Internally this method sets the system properties
|
||||
* <code>http.proxySet</code>, <code>http.proxyHost</code> and
|
||||
* <code>http.proxyPort</code>. Keep in mind that this is valid for
|
||||
* the whole Java Virtual Machine, therefor using this method
|
||||
* can potentially influence other running Helma applications too!
|
||||
* @param {String} proxyString A proxy definition in <code>host:port</code>
|
||||
* format (eg. "proxy.example.com:3128");
|
||||
* @member helma.Http
|
||||
*/
|
||||
helma.Http.setProxy = function(proxyString) {
|
||||
var sys = java.lang.System.getProperties();
|
||||
|
@ -298,7 +499,7 @@ helma.Http.setProxy = function(proxyString) {
|
|||
port = "3128";
|
||||
else if (typeof port == "number")
|
||||
port = port.toString();
|
||||
app.log("helma.Http.setProxy " + proxyString);
|
||||
app.logger.info("helma.Http.setProxy " + proxyString);
|
||||
sys.put("http.proxySet", "true");
|
||||
sys.put("http.proxyHost", host);
|
||||
sys.put("http.proxyPort", port);
|
||||
|
@ -313,7 +514,13 @@ helma.Http.setProxy = function(proxyString) {
|
|||
|
||||
|
||||
/**
|
||||
* return global proxy settings
|
||||
* Returns the proxy setting of the Java Virtual Machine
|
||||
* the Helma application server is running in. If no
|
||||
* proxy is set, this method returns boolean false.
|
||||
* @returns The global proxy setting in <code>host:port</code>
|
||||
* format (eg. "proxy.example.com:3128"), or boolean false.
|
||||
* @type String|Boolean
|
||||
* @member helma.Http
|
||||
*/
|
||||
helma.Http.getProxy = function() {
|
||||
var sys = java.lang.System.getProperties();
|
||||
|
@ -324,10 +531,14 @@ helma.Http.getProxy = function() {
|
|||
|
||||
|
||||
/**
|
||||
* static method to check if a request is authorized or not
|
||||
* @param String username to check req.username against
|
||||
* @param String password to check req.password against
|
||||
* @return Boolean true if request is authorized, false otherwise
|
||||
* Static helper method to check if a request issued agains a
|
||||
* Helma application is authorized or not.
|
||||
* @param {String} name The username to check req.username against
|
||||
* @param {String} pwd The password to check req.password against
|
||||
* @return True if the request is authorized, false otherwise. In
|
||||
* the latter case the current response is reset and the response code
|
||||
* is set to "401" ("Authentication required").
|
||||
* @type Boolean
|
||||
*/
|
||||
helma.Http.isAuthorized = function(name, pwd) {
|
||||
if (!req.username || !req.password ||
|
||||
|
@ -342,11 +553,122 @@ helma.Http.isAuthorized = function(name, pwd) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/** @ignore */
|
||||
helma.Http.toString = function() {
|
||||
return "[helma.Http]";
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new instance of helma.Http.Cookie
|
||||
* @class Instances of this object represent a HTTP cookie
|
||||
* @param {String} name The name of the cookie
|
||||
* @param {String} value The value of the cookie
|
||||
* @returns A newly created Cookie instance
|
||||
* @constructor
|
||||
*/
|
||||
helma.Http.Cookie = function(name, value) {
|
||||
/**
|
||||
* The name of the Cookie
|
||||
* @type String
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The value of the Cookie
|
||||
* @type String
|
||||
*/
|
||||
this.value = value;
|
||||
|
||||
/**
|
||||
* An optional date defining the lifetime of this cookie
|
||||
* @type Date
|
||||
*/
|
||||
this.expires = null;
|
||||
|
||||
/**
|
||||
* An optional path where this cookie is valid
|
||||
* @type String
|
||||
*/
|
||||
this.path = null;
|
||||
|
||||
/**
|
||||
* An optional domain where this cookie is valid
|
||||
* @type String
|
||||
*/
|
||||
this.domain = null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of java.text.SimpleDateFormat used for both parsing
|
||||
* an "expires" string into a date and vice versa
|
||||
* @type java.text.SimpleDateFormat
|
||||
* @final
|
||||
*/
|
||||
helma.Http.Cookie.DATEFORMAT = new java.text.SimpleDateFormat("EEE, dd-MMM-yy HH:mm:ss z");
|
||||
|
||||
|
||||
/**
|
||||
* A regular expression used for parsing cookie strings
|
||||
* @type RegExp
|
||||
* @final
|
||||
*/
|
||||
helma.Http.Cookie.PATTERN = /([^=;]+)=?([^;]*)(?:;\s*|$)/g;
|
||||
|
||||
|
||||
/**
|
||||
* Parses the cookie string passed as argument into an instance of helma.Http
|
||||
* @param {String} cookieStr The cookie string as received from the remote server
|
||||
* @returns An instance of helma.Http.Cookie containing the cookie parameters
|
||||
* @type helma.Http.Cookie
|
||||
*/
|
||||
helma.Http.Cookie.parse = function(cookieStr) {
|
||||
if (cookieStr != null) {
|
||||
var cookie = new helma.Http.Cookie;
|
||||
var m, key, value;
|
||||
while ((m = helma.Http.Cookie.PATTERN.exec(cookieStr)) != null) {
|
||||
key = m[1].trim();
|
||||
value = m[2] ? m[2].trim() : "";
|
||||
switch (key.toLowerCase()) {
|
||||
case "expires":
|
||||
// try to parse the expires date string into a date object
|
||||
try {
|
||||
cookie.expires = helma.Http.Cookie.DATEFORMAT.parse(value);
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
break;
|
||||
case "domain":
|
||||
case "path":
|
||||
cookie[key.toLowerCase()] = value;
|
||||
break;
|
||||
case "secure":
|
||||
break;
|
||||
default:
|
||||
cookie.name = key;
|
||||
cookie.value = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this cookie in a format useable to set the HTTP header field "Cookie"
|
||||
* @return This cookie formatted as HTTP header field value
|
||||
* @type String
|
||||
*/
|
||||
helma.Http.Cookie.prototype.getFieldValue = function() {
|
||||
return this.name + "=" + this.value;
|
||||
};
|
||||
|
||||
/** @ignore */
|
||||
helma.Http.Cookie.prototype.toString = function() {
|
||||
return "[helma.Http.Cookie " + this.name + " " + this.value + "]";
|
||||
};
|
||||
|
||||
helma.lib = "Http";
|
||||
helma.dontEnum(helma.lib);
|
||||
|
@ -354,4 +676,6 @@ for (var i in helma[helma.lib])
|
|||
helma[helma.lib].dontEnum(i);
|
||||
for (var i in helma[helma.lib].prototype)
|
||||
helma[helma.lib].prototype.dontEnum(i);
|
||||
for (var i in helma[helma.lib].Cookie.prototype)
|
||||
helma[helma.lib].Cookie.prototype.dontEnum(i);
|
||||
delete helma.lib;
|
||||
|
|
Loading…
Add table
Reference in a new issue