* 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:
grob 2007-01-30 14:55:39 +00:00
parent 585666e577
commit b11fce933f

View file

@ -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;