001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.reactive.socket; 018 019import java.net.InetSocketAddress; 020import java.net.URI; 021import java.security.Principal; 022import java.util.Collections; 023import java.util.Map; 024 025import reactor.core.publisher.Mono; 026 027import org.springframework.http.HttpHeaders; 028import org.springframework.lang.Nullable; 029import org.springframework.util.Assert; 030 031/** 032 * Simple container of information related to the handshake request that started 033 * the {@link WebSocketSession} session. 034 * 035 * @author Rossen Stoyanchev 036 * @since 5.0 037 * @see WebSocketSession#getHandshakeInfo() 038 */ 039public class HandshakeInfo { 040 041 private final URI uri; 042 043 private final Mono<Principal> principalMono; 044 045 private final HttpHeaders headers; 046 047 @Nullable 048 private final String protocol; 049 050 @Nullable 051 private final InetSocketAddress remoteAddress; 052 053 private final Map<String, Object> attributes; 054 055 @Nullable 056 private final String logPrefix; 057 058 059 /** 060 * Constructor with basic information about the handshake. 061 * @param uri the endpoint URL 062 * @param headers request headers for server or response headers or client 063 * @param principal the principal for the session 064 * @param protocol the negotiated sub-protocol (may be {@code null}) 065 */ 066 public HandshakeInfo(URI uri, HttpHeaders headers, Mono<Principal> principal, @Nullable String protocol) { 067 this(uri, headers, principal, protocol, null, Collections.emptyMap(), null); 068 } 069 070 /** 071 * Constructor targetting server-side use with extra information about the 072 * handshake, the remote address, and a pre-existing log prefix for 073 * correlation. 074 * @param uri the endpoint URL 075 * @param headers request headers for server or response headers or client 076 * @param principal the principal for the session 077 * @param protocol the negotiated sub-protocol (may be {@code null}) 078 * @param remoteAddress the remote address where the handshake came from 079 * @param attributes initial attributes to use for the WebSocket session 080 * @param logPrefix log prefix used during the handshake for correlating log 081 * messages, if any. 082 * @since 5.1 083 */ 084 public HandshakeInfo(URI uri, HttpHeaders headers, Mono<Principal> principal, 085 @Nullable String protocol, @Nullable InetSocketAddress remoteAddress, 086 Map<String, Object> attributes, @Nullable String logPrefix) { 087 088 Assert.notNull(uri, "URI is required"); 089 Assert.notNull(headers, "HttpHeaders are required"); 090 Assert.notNull(principal, "Principal is required"); 091 Assert.notNull(attributes, "'attributes' is required"); 092 093 this.uri = uri; 094 this.headers = headers; 095 this.principalMono = principal; 096 this.protocol = protocol; 097 this.remoteAddress = remoteAddress; 098 this.attributes = attributes; 099 this.logPrefix = logPrefix; 100 } 101 102 103 /** 104 * Return the URL for the WebSocket endpoint. 105 */ 106 public URI getUri() { 107 return this.uri; 108 } 109 110 /** 111 * Return the handshake HTTP headers. Those are the request headers for a 112 * server session and the response headers for a client session. 113 */ 114 public HttpHeaders getHeaders() { 115 return this.headers; 116 } 117 118 /** 119 * Return the principal associated with the handshake HTTP request. 120 */ 121 public Mono<Principal> getPrincipal() { 122 return this.principalMono; 123 } 124 125 /** 126 * The sub-protocol negotiated at handshake time, or {@code null} if none. 127 * @see <a href="https://tools.ietf.org/html/rfc6455#section-1.9"> 128 * https://tools.ietf.org/html/rfc6455#section-1.9</a> 129 */ 130 @Nullable 131 public String getSubProtocol() { 132 return this.protocol; 133 } 134 135 /** 136 * For a server-side session this is the remote address where the handshake 137 * request came from. 138 * @since 5.1 139 */ 140 @Nullable 141 public InetSocketAddress getRemoteAddress() { 142 return this.remoteAddress; 143 } 144 145 /** 146 * Attributes extracted from the handshake request to be added to the 147 * WebSocket session. 148 * @since 5.1 149 */ 150 public Map<String, Object> getAttributes() { 151 return this.attributes; 152 } 153 154 /** 155 * A log prefix used in the handshake to correlate log messages, if any. 156 * @return a log prefix, or {@code null} if not specified 157 * @since 5.1 158 */ 159 @Nullable 160 public String getLogPrefix() { 161 return this.logPrefix; 162 } 163 164 165 @Override 166 public String toString() { 167 return "HandshakeInfo[uri=" + this.uri + ", headers=" + this.headers + "]"; 168 } 169 170}