gexiangdong / tutorial

Spring Boot的例子,包含RESTful API, MVC, JMS, Cache, Mybatis, Cache, Websocket...
http://study.163.com/course/courseMain.htm?courseId=1005213034
MIT License
226 stars 141 forks source link

老师请问nginx代理http请求,那websocket请求怎么办呢,我试了试也没成功 #2

Closed lxge closed 5 years ago

lxge commented 5 years ago

点击连接会请求这样一个地址: http://192.168.1.169:8091/socket/sample/info?t=1573545217658 不用代理:{"entropy":793761487,"origins":[":"],"cookie_needed":true,"websocket":true} 用了代理会返回404 是不是websocket不方便用代理啊,那是不是在new SockJS时候带上不代理的IP, websocket部分不用代理.是这样吗

gexiangdong commented 5 years ago

如果是websocket,需要在nginx里配置 proxy_http_version 1.1; proxy_set_header Connection "Upgrade"; proxy_set_header Upgrade $http_upgrade; 这几句

例如:

    location /socket/sample {
        proxy_pass http://127.0.0.1:8082;
        proxy_http_version 1.1;
        proxy_set_header Host                       $host;
        proxy_set_header X-Real-IP                  $remote_addr;
        proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto    $scheme;
        proxy_redirect                        off;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
lxge commented 5 years ago

如果是websocket,需要在nginx里配置 proxy_http_version 1.1; proxy_set_header Connection "Upgrade"; proxy_set_header Upgrade $http_upgrade; 这几句

例如:

    location /socket/sample {
        proxy_pass http://127.0.0.1:8082;
        proxy_http_version 1.1;
        proxy_set_header Host                       $host;
        proxy_set_header X-Real-IP                  $remote_addr;
        proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto    $scheme;
        proxy_redirect                        off;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

我配了那个了,报错变成了上面那个404,之前报错是连接不了 `map $http_upgrade $connection_upgrade { default upgrade; '' close; }

server
{
    listen 8091;
    #listen [::]:80 default_server ipv6only=on;
    server_name 192.168.1.169;
    index index.html index.htm;
    root  /home/wwwroot/java;

    location / {
        proxy_pass http://192.168.1.169:8090/;
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;
        #CDN发送的头部 设置IP
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect  off;    
    } 

    location /socket {
        #以下配置添加代理头部:
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

    access_log  /home/wwwlogs/java/access.log;
}

`

gexiangdong commented 5 years ago

把location /socket那段改成如下试试:

    location /socket {
        proxy_pass http://192.168.1.169:8090;
        proxy_http_version 1.1;
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect  off;    

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
lxge commented 5 years ago

把location /socket那段改成如下试试:

    location /socket {
        proxy_pass http://192.168.1.169:8090;
        proxy_http_version 1.1;
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect  off;    

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

`connect()..... (index):38 will connect with access-token:http://192.168.1.169:8091/ stomp.min.js:8 Opening Web Socket... websocket.js:6 WebSocket connection to 'ws://192.168.1.169:8091/socket/sample/175/vnofyvmv/websocket' failed: Error during WebSocket handshake: Unexpected response code: 403 WebSocketBrowserDriver @ websocket.js:6 WebSocketTransport @ websocket.js:32 SockJS._connect @ main.js:219 SockJS._receiveInfo @ main.js:193 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 (anonymous) @ info-receiver.js:67 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 (anonymous) @ info-ajax.js:37 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 xhr.onreadystatechange @ abstract-xhr.js:124 abstract-xhr.js:132 POST http://192.168.1.169:8091/socket/sample/175/5rea2s22/xhr_streaming?t=1573550442442 403 AbstractXHRObject._start @ abstract-xhr.js:132 (anonymous) @ abstract-xhr.js:21 setTimeout (async) AbstractXHRObject @ abstract-xhr.js:20 XHRCorsObject @ xhr-cors.js:8 XhrReceiver @ xhr.js:19 Polling._scheduleReceiver @ polling.js:26 Polling @ polling.js:18 SenderReceiver @ sender-receiver.js:20 AjaxBasedTransport @ ajax-based.js:44 XhrStreamingTransport @ xhr-streaming.js:15 SockJS._connect @ main.js:219 SockJS._transportClose @ main.js:299 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 WebSocketTransport.ws.onerror @ websocket.js:54 error (async) WebSocketTransport @ websocket.js:52 SockJS._connect @ main.js:219 SockJS._receiveInfo @ main.js:193 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 (anonymous) @ info-receiver.js:67 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 (anonymous) @ info-ajax.js:37 g @ emitter.js:30 EventEmitter.emit @ emitter.js:50 xhr.onreadystatechange @ abstract-xhr.js:124 XMLHttpRequest.send (async) AbstractXHRObject._start @ abstract-xhr.js:132 (anonymous) @ abstract-xhr.js:21 setTimeout (async) AbstractXHRObject @ abstract-xhr.js:20 XHRLocalObject @ xhr-local.js:8 InfoAjax @ info-ajax.js:19 InfoReceiver._getReceiver @ info-receiver.js:36 InfoReceiver.doXhr @ info-receiver.js:56 (anonymous) @ info-receiver.js:25 setTimeout (async) InfoReceiver @ info-receiver.js:24 SockJS @ main.js:121 makeConnect @ (index):34 onclick @ (index):97 stomp.min.js:8 Web Socket Opened... stomp.min.js:8 >>> CONNECT Authorization:Bearer http://192.168.1.169:8091/ accept-version:1.1,1.0 heart-beat:10000,10000

` 把配置换成下面这个以后 还是会报错的

gexiangdong commented 5 years ago

你直接连,不经过nginx能连成功吗?我感觉这个错误信息,显示nginx已经转发给后面的 springboot了

gexiangdong commented 5 years ago

还有,你可以加2行日志,然后看看日志里都记录啥了,以便确认访问是转发给springboot了

location /socket {
        # 加上下面这2行
        access_log /home/wwwroot/socket-access.log;
        error_log  /home/wwwroot/socket-error.log;

        proxy_pass http://192.168.1.169:8090;
        proxy_http_version 1.1;
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect  off;    

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }
lxge commented 5 years ago

还有,你可以加2行日志,然后看看日志里都记录啥了,以便确认访问是转发给springboot了

location /socket {
        # 加上下面这2行
        access_log /home/wwwroot/socket-access.log;
        error_log  /home/wwwroot/socket-error.log;

        proxy_pass http://192.168.1.169:8090;
        proxy_http_version 1.1;
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect  off;    

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

端口转发:websocket.js:6 WebSocket connection to 'ws://192.168.1.169:8091/socket/sample/254/5nlmyocj/websocket' failed: Error during WebSocket handshake: Unexpected response code: 403 可能java内部实现socket的方式比较复杂吧,具体不大懂,你要不试试呢,我是打包jar运行的

gexiangdong commented 5 years ago

要我试试,你得把代码发给我啊

怀疑是你的java部分代码问题,哪里返回403了,可能是有全局的filter,spring security等之类的东西拦截了请求就直接返回403 你试试前端js直接连你的8090端口的springboot项目,不经过nginx,这样是否还出错

lxge commented 5 years ago

要我试试,你得把代码发给我啊

怀疑是你的java部分代码问题,哪里返回403了,可能是有全局的filter,spring security等之类的东西拦截了请求就直接返回403 你试试前端js直接连你的8090端口的springboot项目,不经过nginx,这样是否还出错

代码就是老师那个啊 github里面有的,我以为你也弄过这个讲的内容

gexiangdong commented 5 years ago

我的代码我当然得试过,可以运行才能放到github上,也才能讲,这是最最最低的职业道德。你这话说得太……

把section-09下载下来,在section-09目录下运行 mvn spring-boot:run 启动后在浏览器输入 http://localhost:8080/index.html?000 点连接,然后可以发消息这些都没问题

但是我的例子里用到的url端口都和你配置的http://192.168.1.169:8091/socket/sample/info?t=1573545217658 不同, 例子里没有info这段

lxge commented 5 years ago

image 在升级成websocket协议的之前一步是访问了一下info 也返回了一些json数据.用代理的情况下会报错了,websocket也会报错的.

lxge commented 5 years ago

我的错,我没发现你就是老师啊(^▽^)

gexiangdong commented 5 years ago

我加了nginx,配置这么写的,

    #这段是为了index.html的访问,也可以把这个index.html拷贝到nginx 的www目录下
    location /index.html {
        proxy_pass http://127.0.0.1:8080;
    }  

  # 这段是转发websocket
    location /socket {

        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect  off;    

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

之后我访问 http://localhost/index.html?000 我的nginx是80端口,成功和,和不用nignx界面一摸一样

gexiangdong commented 5 years ago

我不知道你之前为啥配置 192.168.1.169:8090 nginx和spring-boot不在同一个机器上吗?spring-boot端口你从例子的8080改成了8090吗? 现在我直看到这点区别了,刚刚你的截图是localhost:8080的

lxge commented 5 years ago

恩 刚刚我为了方便就用了windows下面的,之前那些是打包到linux下运行的,8080我在其他地方有用到,就改成8090和nginx8091了. image 老师这边ExceptionHandler重名会报错的,我看半天还以为要添加一个什么插件呢

lxge commented 5 years ago

会不会是linux下面的特殊要求,socket权限啥的,我没有试这个,不过我把jar目录改成777了,还是有报错

gexiangdong commented 5 years ago

肯定不需要jar改成777; 但这涉及到你的jar是怎么运行的,是否正常启动了。 如果是自己在linux命令行启动,java -jar xxx.jar这种样子,你看到终端上最后的信息,就知道是否正常启动了 如果是用systemctl做为daemon运行的,这种情况可能会有权限问题导致启动不起来,权限问题发生在启动的程序需要读写一些文件/目录(例如配置的日志文件)对那些文件没读写权限,给jar设置777没用,需要给对应的目录/文件设置权限 要确认启动起来了没有很简单,浏览器访问下http://192.168.1.169:8090/index.html?000就好了

另外那个excepitonhandler重命名报错,你把具体的错误发给我看看。

lxge commented 5 years ago

老师,这个接口返回正常情况下成功失败都会有code,message,data这些属性,失败的情况是抛出异常,用自定义的excepitonhandler接收吗,那成功的时候呢 if(ts == null) { //404 //return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); throw new ResourceNotFoundException(); } else if (ts.getTvSeriesCharacters().equals(null)) { //403 return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ts); } else { //200 return myExceptionHandler.handleControllerResponse(ts.toString()); //return ResponseEntity.status(HttpStatus.OK).body(ts); } 成功的时候我在那个handler类里这样写的话,返回的结果json的值就都得是字符串了,Map值可以混着来吗,我刚跟着老师学,具体不太清楚. `public class MyExceptionHandler {

@ExceptionHandler(Throwable.class)
@ResponseBody
public ResponseEntity<Object> handleControllerException(
        Throwable ex, WebRequest request){
    Map<String, String> response = new HashMap<>();
    response.put("code", "404");
    response.put("message", "not found");
    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}

@ResponseBody
public ResponseEntity<Object> handleControllerResponse(String data){
    Map<String, String> response = new HashMap<>();
    response.put("code", "200");
    response.put("message", "OK");
    response.put("data", data);
    return ResponseEntity.status(HttpStatus.OK).body(response);
}

}`

异常处理类名与系统注解的类一样报错: image

lxge commented 5 years ago

肯定不需要jar改成777; 但这涉及到你的jar是怎么运行的,是否正常启动了。 如果是自己在linux命令行启动,java -jar xxx.jar这种样子,你看到终端上最后的信息,就知道是否正常启动了 如果是用systemctl做为daemon运行的,这种情况可能会有权限问题导致启动不起来,权限问题发生在启动的程序需要读写一些文件/目录(例如配置的日志文件)对那些文件没读写权限,给jar设置777没用,需要给对应的目录/文件设置权限 要确认启动起来了没有很简单,浏览器访问下http://192.168.1.169:8090/index.html?000就好了

另外那个excepitonhandler重命名报错,你把具体的错误发给我看看。

启动是启动起来了,数据库缓存那部分都没有问题,就是websocket这边会报错,java都打成jar包了,应该怎么给权限啊,我把jar包所在目录给777没有用

lxge commented 5 years ago

老师怎么没有讲一下对接微信这种接口的使用啊,之前我是用php curl实现的,应该java也有.(^▽^)

gexiangdong commented 5 years ago

没别的特殊权限了;只要启动起来了,一般和权限就没关系了。

浏览器访问下http://192.168.1.169:8090/index.html?000 (不过nginx)正常吗?

gexiangdong commented 5 years ago

老师,这个接口返回正常情况下成功失败都会有code,message,data这些属性,失败的情况是抛出异常,用自定义的excepitonhandler接收吗,那成功的时候呢 if(ts == null) { //404 //return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); throw new ResourceNotFoundException(); } else if (ts.getTvSeriesCharacters().equals(null)) { //403 return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ts); } else { //200 return myExceptionHandler.handleControllerResponse(ts.toString()); //return ResponseEntity.status(HttpStatus.OK).body(ts); } 成功的时候我在那个handler类里这样写的话,返回的结果json的值就都得是字符串了,Map值可以混着来吗,我刚跟着老师学,具体不太清楚. `public class MyExceptionHandler {

@ExceptionHandler(Throwable.class)
@ResponseBody
public ResponseEntity<Object> handleControllerException(
      Throwable ex, WebRequest request){
  Map<String, String> response = new HashMap<>();
  response.put("code", "404");
  response.put("message", "not found");
  return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}

@ResponseBody
public ResponseEntity<Object> handleControllerResponse(String data){
  Map<String, String> response = new HashMap<>();
  response.put("code", "200");
  response.put("message", "OK");
  response.put("data", data);
  return ResponseEntity.status(HttpStatus.OK).body(response);
}

}`

异常处理类名与系统注解的类一样报错: image

ExceptionHandler注解的类和执行成功没关系;只有一个访问执行的程序中跑出异常了,而且这个异常自己的程序也没有处理(没有catch),才会进入到对应的ExceptionHandler类里,运行里面的方法,并把结果返回给客户端。

gexiangdong commented 5 years ago

异常处理类名与系统注解的类一样报错: image

这个是我的PPT上举例不严谨,例子代码片段写的不好,是不该重名的,重名的话,不能import进来,需要使用的时候连package name一起写

gexiangdong commented 5 years ago

如果那个socket还调试不出来,而且你有啥可以远程访问你的环境的方法,可以让我远程找找问题,其他我暂时想不到可能了

lxge commented 5 years ago

老师是用的linux吗,代理websocket,会不会linux下面socket权限之类问题

lxge commented 5 years ago

老师上传文件怎么弄啊,我想试一下传文件到服务器中,这边用fastdfs,可是我不知道这个multipartfile格式的数据除了表单提交有,自己怎么定义一个,试了半天都没成功... ` public Map<String, String> upload(){ // if (log.isTraceEnabled()) { // log.trace("上传文件:"+ filePath); // } File file = new File(filePath); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody("file", file); HttpEntity entity = builder.build();

    //fastdfsClientUtil.upload(entity);

    Map<String, String> result = new HashMap<>();
    result.put("message", "上传文件:"+filePath);
    return result;
}`

被调用的方法 ` 上传文件 public String upload(MultipartFile myfile) throws Exception{ //文件名 String originalFilename = myfile.getOriginalFilename().substring(myfile.getOriginalFilename().lastIndexOf(".") + 1); // 文件扩展名 String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());

  StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(myfile.getInputStream(), myfile.getSize(),originalFilename , null);

  String path = storePath.getFullPath();

  return path;

}`

lxge commented 5 years ago

abstract-xhr.js:132 GET http://192.168.1.169:8091/socket/sample/info?t=1573727624358 404 (Not Found) 就添加nginx代理会连接不上websocket,不代理是正常的

lxge commented 5 years ago

image image websocket连接第一步会请求这个地址,代理的就会报错,看着已经代理给tomcat了,这种错误比较难找.

gexiangdong commented 5 years ago

浏览器访问下http://192.168.1.169:8090/index.html?000 (不过nginx)正常吗?

其他问题,或继续这个问题,请加我qq 1327303702 继续, github issue不是讨论版,在这讨论有违github issue初衷