专栏首页10km的专栏nanohttpd:实现跨域(CORS)请求

nanohttpd:实现跨域(CORS)请求

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/10km/article/details/102568909

NanoHTTPD是一个轻量级的HTTP服务器,可以很方便地嵌入到Java程序中。所以在android平台上有广泛的使用。 NanoHTTPD默认是不支持访问跨域(CORS)请求的。如果希望自己的NanoHTTPD服务支持CORS,就要自己实现对CORS请求的响应。 关于什么是CORS,这个文档有非常详细、清晰、全面的阐述: 《HTTP访问控制(CORS)》,如果还不太清楚CORS机制的童鞋,建议先看这篇 文章补补课。

实现对跨域访问的支持的关键就是要响应跨请求,跨域请求的METHOD为OPTIONS,对收到的HTTP请求要先识别是否为跨域请求,如果是就发送正确的响应。下面是nanohttpd响应CORS请求的基本逻辑

    @Override
    public Response serve(IHTTPSession session) {
    	// 判断是否为跨域预请求
    	if(isPreflightRequest(session)){
    		// 如果是则发送CORS响应告诉浏览HTTP服务支持的METHOD及HEADERS和请求源
    		return responseCORS(session);
    	}
    	// 业务逻辑
    	.....
    	/////
    	return wrapResponse(session,responseAck(ack));
    }

下面是上述代码中调用的子方法的实现, 注意:因为nanohttp的headers中所有的key都是全小写,所以你会发现下面的代码,从headers获取header时,header的名字都是小写的。

	/**
	 * 判断是否为CORS 预检请求请求(Preflight)
	 * @param session
	 * @return
	 */
	private static boolean isPreflightRequest(IHTTPSession session) {
		Map<String, String> headers = session.getHeaders();
		return Method.OPTIONS.equals(session.getMethod()) 
				&& headers.containsKey("origin") 
				&& headers.containsKey("access-control-request-method") 
				&& headers.containsKey("access-control-request-headers");
	}
		/**
	 * 向响应包中添加CORS包头数据
	 * @param session
	 * @return
	 */
	private Response responseCORS(IHTTPSession session) {
		Response resp = wrapResponse(session,newFixedLengthResponse(""));
		Map<String, String> headers = session.getHeaders();
		resp.addHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS");

		String requestHeaders = headers.get("access-control-request-headers");
		String allowHeaders = MoreObjects.firstNonNull(requestHeaders, "Content-Type");
		resp.addHeader("Access-Control-Allow-Headers", allowHeaders);
		//resp.addHeader("Access-Control-Max-Age", "86400");
		resp.addHeader("Access-Control-Max-Age", "0");
		return resp;
	}
	/**
	 * 封装响应包
	 * @param session http请求
	 * @param resp 响应包
	 * @return resp
	 */
	private Response wrapResponse(IHTTPSession session,Response resp) {
		if(null != resp){			
			Map<String, String> headers = session.getHeaders();
			resp.addHeader("Access-Control-Allow-Credentials", "true");
			// 如果请求头中包含'Origin',则响应头中'Access-Control-Allow-Origin'使用此值否则为'*'
			// nanohttd将所有请求头的名称强制转为了小写
			String origin = MoreObjects.firstNonNull(headers.get("origin", "*");
			resp.addHeader("Access-Control-Allow-Origin", origin);
			
			String  requestHeaders = headers.get("access-control-request-headers");
			if(requestHeaders != null){
				resp.addHeader("Access-Control-Allow-Headers", requestHeaders);
			}
		}
		return resp;
	}

完整的代码参见码云仓库代码: gu.dtalk.engine.DtalkHttpServer.java

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux(常用)命令

    jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令, 简...

    郭大侠
  • 项目参数外部配置化

    开发一个项目,参数是必不可少的,规模越大参数越多。在不同的测试环境中部署,或者是依赖项目的信息发生了变化,你有没有想跳楼的感觉?如果有,恭喜你,你至少已经不是在...

    程序猿讲故事
  • Springboot输出PDF文件

    有个人(死需求)跑过来跟你说,这些都给我输出成报告,pdf格式的,所以就有了下面这个,做一下笔记,以后有用直接过来拿。在网上找了一下,发现大家都是在用itext...

    用户3467126
  • 计算机基础知识

    计算机基本的硬件由:CPU / 内存 / 主板 / 硬盘 / 网卡 / 显卡 等组成,只有硬件但硬件之间无法进行交流和通信。

    郭大侠
  • python2与python3 版本区别

    郭大侠
  • 第30次文章:文本大对象+ORM

    本周主要介绍JDBC中的两个文本大对象CLOB和BLOB,并根据前面在JDBC中编程的分析,封装了一个连接数据库和关闭流操作的工具类JDBCUtil。最后涉及了...

    鹏-程-万-里
  • JSON金额解析BUG的解决过程

    这是在我们开发的一个支付系统中暴露的一个BUG,问题本身比较简单,有意思的是解决问题的过程。将过程分享出来,希望能够对大家有所帮助。

    程序猿讲故事
  • 第32次文章:手写SORM框架(二)

    在上周,我们将整个SORM的框架结构梳理了一下,本周开始对整个框架的每个细节步骤进行相关的填充。目前还没有把整个框架全部搭建起来,只完成了一小部分,这周我们就对...

    鹏-程-万-里
  • 第31次文章:手写SORM框架(一)

    在上周的末尾,我们介绍了ORM框架,将数据库和Java程序中的数据类型进行关联。这周我们进入SORM框架深入探究,最后手写一个SORM框架。作者也是第一次学习,...

    鹏-程-万-里
  • 第33次文章:SORM框架(三)

    本周将SORM框架的基本功能已经全部填充起来了,形成了SORM框架的1.0版本,有兴趣的同学可以通过下面的链接获取源码哟!下周将进入SORM框架的升级阶段,在现...

    鹏-程-万-里

扫码关注云+社区

领取腾讯云代金券