very light server side HTTP request management,

  • Thread starter Frederic Duclos
  • Start date
F

Frederic Duclos

Hi,

I need to manage in a java application very few POST and GET HTTP
requests, and particularly, i need to extract the body of a post
request.
I don't want to use any servlet on high level web techno since the Web
is not the main goal of my application, so i don't want to start a new
JVM such as Tomcat...

So i am looking for Java classes that provide the following feature:
- reification of a GET and POST requests from a socket Stream, that
contains all needed getters to access the different part of the
request,
- reification of a GET or POST response to a socket stream, that
contains all needed setters.

any ideas ?

Thanks,

Frederic Duclos
 
R

Ryan Stewart

Frederic Duclos said:
Hi,

I need to manage in a java application very few POST and GET HTTP
requests, and particularly, i need to extract the body of a post
request.
I don't want to use any servlet on high level web techno since the Web
is not the main goal of my application, so i don't want to start a new
JVM such as Tomcat...

So i am looking for Java classes that provide the following feature:
- reification of a GET and POST requests from a socket Stream, that
contains all needed getters to access the different part of the
request,
- reification of a GET or POST response to a socket stream, that
contains all needed setters.

any ideas ?
Read the spec and write them:
http://www.w3.org/Protocols/rfc2616/rfc2616.html. It only took me a couple
of days. You could even use the javax.servlet.http interfaces if you like (I
didn't).
 
B

Bjorn Borud

[[email protected] (Frederic Duclos)]
|
| any ideas ?

I just included Jetty in one of my projects recently to do more or
less the same. it took about 10 minutes to have it up and running
inside my application (from the time I looked at the Jetty web pages).
I have some set-up code and then I just subclassed AbstractHttpHandler
and implemented the handle() method.

possibly not as lean as you intended, but it is a really quick and
easy solution.

and *if* you would want to use a servlet-container later, Jetty
already has that available.

-Bjørn
 
J

Jon Caldwell

Ryan said:
Read the spec and write them:
http://www.w3.org/Protocols/rfc2616/rfc2616.html. It only took me a couple
of days. You could even use the javax.servlet.http interfaces if you like (I
didn't).


I believe this question was asked because he didn't want to write his own.

There are some tricky parts of implementing an operational HTTP client,
even for simple GET requests (Chunked encoding on an IIS server...
yuck!, Maybe Bill Gates should read the chunked encoding RFC).

Jakarta Commons has a wonderful one:
http://jakarta.apache.org/commons/httpclient/
 
J

Jon Caldwell

Jon said:
I believe this question was asked because he didn't want to write his own.

There are some tricky parts of implementing an operational HTTP client,
even for simple GET requests (Chunked encoding on an IIS server...
yuck!, Maybe Bill Gates should read the chunked encoding RFC).

Jakarta Commons has a wonderful one:
http://jakarta.apache.org/commons/httpclient/

Sorry, I have yet to finish my coffee this morning. You want to handle
client requests, not generate them. The Jetty suggestion is the one I
would have personally used.
 
R

Ryan Stewart

Jon Caldwell said:
Sorry, I have yet to finish my coffee this morning. You want to handle
client requests, not generate them. The Jetty suggestion is the one I
would have personally used.

This is all well and good, but you all are suggesting HTTP servers when the
OP seems to me to be looking for two simple classes: an HttpRequest and an
HttpResponse.
 
R

Ryan Stewart

Frederic Duclos said:
Hi,

I need to manage in a java application very few POST and GET HTTP
requests, and particularly, i need to extract the body of a post
request.
I don't want to use any servlet on high level web techno since the Web
is not the main goal of my application, so i don't want to start a new
JVM such as Tomcat...
Hi again. After the other posts here, I'm wondering if I'm misreading what
you want, but if you only want a class to represent a request and one to
represent a response, I have something you might be able to work with. I
found these looking through some old files. I think they are early versions,
and the HttpRequest was always ahead of HttpResponse in development, but
depending on what you want, this may give you a quick solution with little
time invested. Here is the request class: (Apologies to everyone for the
long post. Hopefully this will be useful to others as well.)
//***************
// Start code
//***************
import java.util.*;

public class HTTPRequest {

private HashMap parameters = new HashMap();
private String header;
private byte[] body;
private boolean valid = true;

public HTTPRequest() {
}

public HTTPRequest(String request) {
int headerEnd = request.indexOf("\n\n");
if (headerEnd == -1) {
this.header = request;
} else {
this.header = request.substring(0, headerEnd);
}
parse();
}

private void parse() {
String[] lines = header.split("\n");
if (lines.length > 0) {
// First is method, resource, and version
String[] firstLine = lines[0].split(" ");
if (firstLine.length == 3) {
parameters.put("Method", firstLine[0]);
parameters.put("Resource", firstLine[1]);
parameters.put("Version", firstLine[2]);
for (int i=1; i<lines.length; i++) {
int colonPos = lines.indexOf(':');
if (colonPos != -1) {
String key = lines.substring(0, colonPos).trim();
String value = lines.substring(colonPos +
1).trim();
parameters.put(key, value);
} else {
valid = false;
}
}
} else {
valid = false;
}
}
}

public String getProperty(String parameter) {
return (String)parameters.get(parameter);
}

public void setProperty(String key, String value) {
parameters.put(key, value);
}

public Set getKeys() {
return parameters.keySet();
}

public byte[] getBody() {
return this.body;
}

public void setBody(byte[] body) {
this.body = body;
}

public boolean isValid() {
if (parameters.get("Method") == null) {
valid = false;
} else {
String method = (String) parameters.get("Method");
if (!(method.equalsIgnoreCase("get")
|| method.equalsIgnoreCase("post")
|| method.equalsIgnoreCase("options")
|| method.equalsIgnoreCase("head")
|| method.equalsIgnoreCase("put")
|| method.equalsIgnoreCase("delete")
|| method.equalsIgnoreCase("trace")
|| method.equalsIgnoreCase("connect"))) {
valid = false;
}
}

if (parameters.get("Resource") == null) {
valid = false;
} else {
String resource = (String) parameters.get("Resource");
if (!resource.startsWith("/")) {
valid = false;
}
}

if (parameters.get("Version") == null) {
String version = (String) parameters.get("Version");
if (!version.toLowerCase().startsWith("http")) {
valid = false;
}
}
return valid;
}

public byte[] getBytes() {
StringBuffer header = new StringBuffer();
header.append(parameters.get("Method") + " ");
header.append(parameters.get("Resource") + " ");
header.append(parameters.get("Version") + "\n");
Set keys = parameters.keySet();
Iterator keyIterator = keys.iterator();
while (keyIterator.hasNext()) {
String key = (String)keyIterator.next();
if (!(key.equals("Method") || key.equals("Resource")
|| key.equals("Version"))) {
header.append(key);
header.append(": ");
header.append((String)parameters.get(key));
header.append("\n");
}
}
header.append("\n");
byte[] result;
if (body == null) {
result = header.toString().getBytes();
} else {
byte[] headerAsBytes = header.toString().getBytes();
int length = headerAsBytes.length + body.length;
result = new byte[length];
System.arraycopy(headerAsBytes, 0, result, 0,
headerAsBytes.length);
System.arraycopy(body, 0, result, headerAsBytes.length,
body.length);
}
return result;
}

public String toString() {
return new String(getBytes());
}
}
//***************
// End code
//***************

And the response :
//***************
// Start code
//***************
import java.io.*;
import java.util.*;

public class HTTPResponse {

private String header;
private HashMap parameters = new HashMap();
private byte[] body;
private byte[] endResponse = {};

public HTTPResponse(String responseText) {
int headerEnd = responseText.indexOf("\n\n");
if (headerEnd == -1) {
this.header = responseText;
} else {
this.header = responseText.substring(0, headerEnd);
}
parse();
}

public HTTPResponse(String version, int statusCode, String reasonPhrase)
{
parameters.put("Version", version);
parameters.put("Status Code", String.valueOf(statusCode));
parameters.put("Reason Phrase", reasonPhrase);
}

public HTTPResponse(String version, int statusCode, String reasonPhrase,
byte[] body) {
parameters.put("Version", version);
parameters.put("Status Code", String.valueOf(statusCode));
parameters.put("Reason Phrase", reasonPhrase);
this.body = body;
}

private void parse() {
String[] lines = header.split("\n");
if (lines.length > 0) {
// First is version, status code, and reason phrase
String[] firstLine = lines[0].split(" ");
if (firstLine.length == 3) {
parameters.put("Version", firstLine[0]);
parameters.put("Status Code", firstLine[1]);
parameters.put("Reason Phrase", firstLine[2]);
for (int i=0; i<lines.length; i++) {
int colonPos = lines.indexOf(':');
if (colonPos != -1) {
String key = lines.substring(0, colonPos).trim();
String value = lines.substring(colonPos +
1).trim();
parameters.put(key, value);
}
}
}
}
}

public String getProperty(String key) {
return (String)parameters.get(key);
}

public void setProperty(String key, String value) {
parameters.put(key, value);
}

public Set getKeys() {
return parameters.keySet();
}

public String getVersion() {
return (String)parameters.get("Version");
}

public void setVersion(String version) {
parameters.put("Version", version);
}

public String getStatusCode() {
return (String)parameters.get("Status Code");
}

public void setStatusCode(String statusCode) {
parameters.put("Status Code", statusCode);
}

public String getReasonPhrase() {
return (String)parameters.get("Reason Phrase");
}

public void setReasonPhrase(String reasonPhrase) {
parameters.put("Reason Phrase", reasonPhrase);
}

public String getContentType() {
return (String)parameters.get("Content-Type");
}

public void setContentType(String contentType) {
parameters.put("Content-Type", contentType);
}

public byte[] getBytes() {
StringBuffer header = new StringBuffer();
header.append(getVersion() + " ");
header.append(getStatusCode() + " ");
header.append(getReasonPhrase() + "\n");
Set keys = parameters.keySet();
Iterator keyIterator = keys.iterator();
while (keyIterator.hasNext()) {
String key = (String)keyIterator.next();
if (!(key.equals("Version") || key.equals("Status Code")
|| key.equals("Reason Phrase"))) {
header.append(key);
header.append(": ");
header.append((String)parameters.get(key));
header.append("\n");
}
}
header.append("\n");

byte[] headerBytes = header.toString().getBytes();
byte[] result;
if (body == null) {
result = new byte[headerBytes.length + endResponse.length];
System.arraycopy(headerBytes, 0, result, 0, headerBytes.length);
System.arraycopy(endResponse, 0, result, headerBytes.length,
endResponse.length);
} else {
result = new byte[headerBytes.length + body.length
+ endResponse.length];
System.arraycopy(headerBytes, 0, result, 0, headerBytes.length);
System.arraycopy(body, 0, result, headerBytes.length,
body.length);
System.arraycopy(endResponse, 0, result, headerBytes.length
+ body.length, endResponse.length);
}
return result;
}
}
//***************
// End code
//***************
 
R

Ryan Stewart

[a lot of code]
Grr. Watch for some line wrapping. All that was under 80 columns. What
decides where lines are wrapped on usenet?
 
C

Chris Uppal

Ryan said:
Grr. Watch for some line wrapping. All that was under 80 columns. What
decides where lines are wrapped on usenet?

In your case, probably the sending client. NNTP servers are allowed to wrap
posts, IIRC, but I've never seen one do it myself. OE has a configurable
option to set where it will wrap plain text, I think it defaults to column 72.
(If you don't have "send immediately" set, then you can see the line-wrapped
version of your post in your outbox while it's waiting to be sent.)

BTW, the way I read the OP's post, he's really looking for a small
web-server -- he wants the request/response objects to be able to send/recieve
themselves from a socket, and once you've got that, you pretty much have an
entire HTTP server.

-- chris
 
R

Ryan Stewart

Chris Uppal said:
In your case, probably the sending client. NNTP servers are allowed to wrap
posts, IIRC, but I've never seen one do it myself. OE has a configurable
option to set where it will wrap plain text, I think it defaults to column 72.
(If you don't have "send immediately" set, then you can see the line-wrapped
version of your post in your outbox while it's waiting to be sent.)
Thanks for the tip. OE was set to 76.
BTW, the way I read the OP's post, he's really looking for a small
web-server -- he wants the request/response objects to be able to send/recieve
themselves from a socket, and once you've got that, you pretty much have an
entire HTTP server.
Well, whatever he wants, all his bases should be covered now :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,151
Latest member
JaclynMarl
Top