Java HTTP服务器-为favicon.ico提供服务
我正在尝试设置自己的JavaHTTP服务器,以便更好地理解http服务器以及在web的保护下发生的事情。我已经开发了一个非常简单的服务器,能够同时提供html页面和JSON格式的数据。然后我看到浏览器(我正在使用chrome,但假设其他浏览器也是一样)正在发送一个favicon.ico请求。我能够在我的服务器上识别该请求,因此我尝试提供一个随机下载的图标,并将其大小调整为16x16像素的png格式,因为这是互联网所要求的大小。这是我的代码,请注意,它不应该是任何专业的东西,而只是一些能满足我基本教育目的的东西:Java HTTP服务器-为favicon.ico提供服务,java,http,web,server,Java,Http,Web,Server,我正在尝试设置自己的JavaHTTP服务器,以便更好地理解http服务器以及在web的保护下发生的事情。我已经开发了一个非常简单的服务器,能够同时提供html页面和JSON格式的数据。然后我看到浏览器(我正在使用chrome,但假设其他浏览器也是一样)正在发送一个favicon.ico请求。我能够在我的服务器上识别该请求,因此我尝试提供一个随机下载的图标,并将其大小调整为16x16像素的png格式,因为这是互联网所要求的大小。这是我的代码,请注意,它不应该是任何专业的东西,而只是一些能满足我基本
[set up ServerSocket and listen]
public static String err_header = "HTTP/1.1 500 ERR\nAccess-Control-Allow-Origin: *";
public static String success_header = "HTTP/1.1 200 OK\nAccess-Control-Allow-Origin: *";
public static String end_header = "\r\n\r\n";
while(true){
try{
System.out.println("Listening for new connections");
clientSocket = server.accept();
System.out.println("Connection established");
InputStreamReader isr = new InputStreamReader(clientSocket.getInputStream());
BufferedReader reader = new BufferedReader(isr);
String getLine = reader.readLine();//first line of HTTP request
handleRequest(getLine,clientSocket);
}//end of try
catch(Exception e){
[error stuff]
}//end of catch
}//end of while
HandlerRequest方法:
public static void handleRequest(String getLine,Socket clientSocket) throws Exception{
if(getLine.substring(5,16).equals("favicon.ico")){
List<String> iconTag = new ArrayList<String>();
iconTag.add("\nContent-Type: image/png");
handleFileRequest("[file]",iconTag,clientSocket);
}//end of if
else{
handleFileRequest("[file]",clientSocket);
}//end of else
}//end of handleRequest
publicstaticvoidhandlerequest(stringgetline,socketclientsocket)抛出异常{
if(getLine.substring(5,16).equals(“favicon.ico”)){
List iconTag=new ArrayList();
iconTag.add(“\n内容类型:image/png”);
handleFileRequest(“[file]”,iconTag,clientSocket);
}//if结束
否则{
handleFileRequest(“[file]”,clientSocket);
}//别有用心
}//HandlerRequest结束
HandleFile请求图像:
public static void handleFileRequest(String fileName,List<String> headerTags,Socket clientSocket) throws Exception{
OutputStream out = clientSocket.getOutputStream();
BufferedReader read = new BufferedReader(new FileReader(fileName));
out.write(success_header.getBytes("UTF-8"));
Iterator<String> itr = headerTags.iterator();
while(itr.hasNext()){
out.write(itr.next().getBytes("UTF-8"));
}//end of while
out.write(end_header.getBytes("UTF-8"));
String readLine = "";
while((readLine = read.readLine())!=null){
out.write(readLine.getBytes("UTF-8"));
}//end of while
out.flush();
out.close();
}//end of handleFileRequest
publicstaticvoidhandlefilerequest(字符串文件名、列表头标签、套接字clientSocket)引发异常{
OutputStream out=clientSocket.getOutputStream();
BufferedReader read=新的BufferedReader(新文件读取器(文件名));
out.write(success_header.getBytes(“UTF-8”);
迭代器itr=headerTags.Iterator();
while(itr.hasNext()){
out.write(itr.next().getBytes(“UTF-8”);
}//结束
out.write(end_header.getBytes(“UTF-8”);
字符串readLine=“”;
而((readLine=read.readLine())!=null){
out.write(readLine.getBytes(“UTF-8”);
}//结束
out.flush();
out.close();
}//handleFileRequest结束
它似乎可以工作,当服务器发送文件时,浏览器显示200 OK响应,但没有favicon,当我将网络请求过滤为仅图像时,有一个图像是由正在服务的页面请求的,但favicon请求没有列在那里(favicon请求在“其他”部分)。类似地,当单击另一个图像时,图像会显示在预览中,而favicon请求的情况并非如此。截图:
同时,这是另一幅图像的外观,它在页面中显示得很好:
我也尝试过包含内容长度标题,但这似乎没有什么不同。我错过了什么明显的东西吗
另外,我只想澄清一下,我知道我可以在实际的html页面中包含favicon,目标不是这样做,而是理解它是如何工作的。读取二进制文件
看来这封信的内容没有正确送达
我怀疑这很可能是因为您阅读其内容的方式:
逐行读取二进制内容是不合适的,
因为线的概念,还有UTF-8编码,
在二进制文件的上下文中没有意义。
这样你就不能一行一行地正确阅读二进制内容,
因为BufferedReader
的readLine
方法不会返回整行,因为它会从末尾剥离换行符。
您无法手动添加换行符,因为您无法确切知道它是什么
以下是读取二进制文件内容的一种更简单、正确的方法:
byte[] bytes = Files.readAllBytes(Paths.get("/path/to/file"));
一旦有了这些,就可以使用bytes.length
的值轻松生成具有内容长度的正确文件头
在浏览器中访问页面时会发生什么情况
如果我们澄清一些事情,似乎对你有好处
在浏览器中打开URL时,
浏览器向web服务器发送GET请求,以下载您指定的原始URL的内容
一旦获得页面内容,它将发送进一步的GET请求:
- 如果还没有,就去拿一个。此文件的位置可以在HTML文档中指定,否则浏览器将在默认情况下尝试获取
SERVERNAME/favicon.ico
- 获取文档中任何(有效)
标记的
属性中指定的图像src
- 获取文档中任何(有效)
标记的
属性中指定的样式表href
- 。。。类似地,对于
标记,等等
name:value
格式,每一行必须以\n
结尾。
必须至少有一个内容类型
标题。
标题必须以空行结尾终止标头的空白行之后, 内容可以是任何内容,甚至是二进制。 举例说明,, 考虑<代码> CURL< /COD>命令,它将URL的内容转储到标准输出。 如果运行
将url卷曲到某个html文件
,
您将看到html文件的内容。
如果运行指向某个图像文件的curl url
,
您将看到图像文件的内容。
它将无法读取,并且您的终端可能会发出奇怪的声音。
您可以将输出重定向到具有curl url to some image file>image.png
的文件,
这会给你一个图像文件,
二进制内容,
可以在任何图像查看器工具中打开byte[] bytes = Files.readAllBytes(Paths.get("/path/to/file"));
curl -o file url-to-favicon
cmp file /path/to/original
HttpServer server = HttpServer.create(new InetSocketAddress(1234), 0);
server.createContext("/favicon.ico", t -> {
byte[] bytes = Files.readAllBytes(Paths.get("/path/to/favicon"));
t.sendResponseHeaders(200, bytes.length);
try (OutputStream os = t.getResponseBody()) {
os.write(bytes);
}
});
server.createContext("/", t -> {
Charset charset = StandardCharsets.UTF_8;
List<String> lines = Files.readAllLines(Paths.get("/path/to/index"), charset);
t.sendResponseHeaders(200, 0);
try (OutputStream os = t.getResponseBody()) {
for (String line : lines) {
os.write((line + "\n").getBytes(charset));
}
}
});
server.start();