@@ -2,7 +2,6 @@
 | 
			
		||||
 * Module dependencies.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import * as server from "../server"
 | 
			
		||||
// const http = require("http")
 | 
			
		||||
// const Server = require("./server")
 | 
			
		||||
import { Server } from './server'
 | 
			
		||||
@@ -18,7 +17,7 @@ import { Server } from './server'
 | 
			
		||||
 | 
			
		||||
function attach(srv, options) {
 | 
			
		||||
    const engine = new Server(options)
 | 
			
		||||
    engine.attach(server.attach(srv, options), options)
 | 
			
		||||
    engine.attach(srv, options)
 | 
			
		||||
    return engine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
/// <reference types="@ccms/nashorn" />
 | 
			
		||||
/// <reference types="@javatypes/tomcat-websocket-api" />
 | 
			
		||||
 | 
			
		||||
import * as server from './server'
 | 
			
		||||
import { Server, ServerOptions } from './socket.io'
 | 
			
		||||
 | 
			
		||||
interface SocketIOStatic {
 | 
			
		||||
@@ -38,9 +39,21 @@ interface SocketIOStatic {
 | 
			
		||||
 | 
			
		||||
type SocketStatic = SocketIOStatic & { Instance?: symbol }
 | 
			
		||||
 | 
			
		||||
let singletonServer: Server
 | 
			
		||||
 | 
			
		||||
// @ts-ignore
 | 
			
		||||
let io: SocketStatic = function (pipeline: any, options: Partial<ServerOptions>) {
 | 
			
		||||
    return new Server(pipeline, options)
 | 
			
		||||
let io: SocketStatic = function io(pipeline: any, options: Partial<JavaServerOptions>, singleton = true) {
 | 
			
		||||
    if (singleton) {
 | 
			
		||||
        if (!singletonServer) {
 | 
			
		||||
            singletonServer = new Server(server.attach(pipeline, options), options)
 | 
			
		||||
            process.emit('websocket.create', singletonServer)
 | 
			
		||||
            process.on('exit', () => {
 | 
			
		||||
                singletonServer.close()
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
        return singletonServer
 | 
			
		||||
    }
 | 
			
		||||
    return new Server(server.attach(pipeline, options), options)
 | 
			
		||||
}
 | 
			
		||||
io.Instance = Symbol("@ccms/websocket")
 | 
			
		||||
export default io
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ export enum ServerEvent {
 | 
			
		||||
export interface JavaServerOptions extends ServerOptions {
 | 
			
		||||
    event?: EventEmitter
 | 
			
		||||
    root?: string
 | 
			
		||||
    httpRequestHandler?: (ctx, request) => void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export abstract class WebSocketServer extends EventEmitter {
 | 
			
		||||
@@ -30,7 +31,6 @@ export abstract class WebSocketServer extends EventEmitter {
 | 
			
		||||
        this.instance = instance
 | 
			
		||||
        this.options = options
 | 
			
		||||
        this.clients = new Map()
 | 
			
		||||
        console.debug('create websocket server from ' + this.constructor.name)
 | 
			
		||||
        this.initialize()
 | 
			
		||||
    }
 | 
			
		||||
    protected onconnect(handler: any) {
 | 
			
		||||
@@ -56,7 +56,7 @@ export abstract class WebSocketServer extends EventEmitter {
 | 
			
		||||
        if (this.clients.has(id)) {
 | 
			
		||||
            this.clients.has(id) && callback(this.clients.get(id))
 | 
			
		||||
        } else {
 | 
			
		||||
            console.debug('ignore execute', handler, 'callback', callback)
 | 
			
		||||
            console.trace('ignore execute', handler, 'callback', callback)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public close() {
 | 
			
		||||
@@ -75,7 +75,7 @@ export const attach = (instance, options) => {
 | 
			
		||||
    options = Object.assign({
 | 
			
		||||
        event: new EventEmitter(),
 | 
			
		||||
        path: '/ws',
 | 
			
		||||
        root: root + '/wwwroot',
 | 
			
		||||
        root: root + Java.type("java.io.File").separatorChar + 'wwwroot',
 | 
			
		||||
    }, options)
 | 
			
		||||
    let WebSocketServerImpl = undefined
 | 
			
		||||
    if (instance.class.name.startsWith('io.netty.channel')) {
 | 
			
		||||
@@ -83,5 +83,6 @@ export const attach = (instance, options) => {
 | 
			
		||||
    } else {
 | 
			
		||||
        WebSocketServerImpl = require("./tomcat").TomcatWebSocketServer
 | 
			
		||||
    }
 | 
			
		||||
    console.debug('create websocket server from ' + WebSocketServerImpl.name)
 | 
			
		||||
    return new WebSocketServerImpl(instance, options)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,40 +23,46 @@ export class HttpRequestHandler extends HttpRequestHandlerAdapter {
 | 
			
		||||
        super()
 | 
			
		||||
        this.root = options.root
 | 
			
		||||
        this.ws = options.path
 | 
			
		||||
        if (options.httpRequestHandler) {
 | 
			
		||||
            this.httpRequestHandler = options.httpRequestHandler
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    channelRead0(ctx: any, request: any) {
 | 
			
		||||
        if (request.getUri().startsWith(this.ws)) {
 | 
			
		||||
            ctx.channel().attr(AttributeKeys.Request).set(request)
 | 
			
		||||
            ctx.fireChannelRead(request.retain())
 | 
			
		||||
        } else {
 | 
			
		||||
            ctx.executor().execute(new Runnable({
 | 
			
		||||
                run: () => {
 | 
			
		||||
                    if (HttpHeaders.is100ContinueExpected(request)) {
 | 
			
		||||
                        ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE))
 | 
			
		||||
                    }
 | 
			
		||||
                    let filename = request.getUri().split('?')[0].substr(1)
 | 
			
		||||
                    let file = new File(this.root, filename || 'index.html')
 | 
			
		||||
                    if (!file.exists() || !file.isFile()) {
 | 
			
		||||
                        ctx.write(new DefaultHttpResponse(request.getProtocolVersion(), HttpResponseStatus.NOT_FOUND))
 | 
			
		||||
                        ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE)
 | 
			
		||||
                        return
 | 
			
		||||
                    }
 | 
			
		||||
                    let response = new DefaultHttpResponse(request.getProtocolVersion(), HttpResponseStatus.OK)
 | 
			
		||||
                    response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html charset=UTF-8")
 | 
			
		||||
                    let raf = new RandomAccessFile(file, 'r')
 | 
			
		||||
                    let keepAlive = HttpHeaders.isKeepAlive(request)
 | 
			
		||||
                    if (keepAlive) {
 | 
			
		||||
                        response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, file.length())
 | 
			
		||||
                        response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE)
 | 
			
		||||
                    }
 | 
			
		||||
                    ctx.write(response)
 | 
			
		||||
                    ctx.write(new DefaultFileRegion(raf.getChannel(), 0, raf.length()))
 | 
			
		||||
                    let future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
 | 
			
		||||
                    if (!keepAlive) {
 | 
			
		||||
                        future.addListener(ChannelFutureListener.CLOSE)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }))
 | 
			
		||||
            this.httpRequestHandler(ctx, request)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    httpRequestHandler(ctx: any, request: any) {
 | 
			
		||||
        ctx.executor().execute(new Runnable({
 | 
			
		||||
            run: () => {
 | 
			
		||||
                if (HttpHeaders.is100ContinueExpected(request)) {
 | 
			
		||||
                    ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE))
 | 
			
		||||
                }
 | 
			
		||||
                let filename = request.getUri().split('?')[0].substr(1)
 | 
			
		||||
                let file = new File(this.root, filename || 'index.html')
 | 
			
		||||
                if (!file.exists() || !file.isFile()) {
 | 
			
		||||
                    ctx.write(new DefaultHttpResponse(request.getProtocolVersion(), HttpResponseStatus.NOT_FOUND))
 | 
			
		||||
                    ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT).addListener(ChannelFutureListener.CLOSE)
 | 
			
		||||
                    return
 | 
			
		||||
                }
 | 
			
		||||
                let response = new DefaultHttpResponse(request.getProtocolVersion(), HttpResponseStatus.OK)
 | 
			
		||||
                response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html charset=UTF-8")
 | 
			
		||||
                let raf = new RandomAccessFile(file, 'r')
 | 
			
		||||
                let keepAlive = HttpHeaders.isKeepAlive(request)
 | 
			
		||||
                if (keepAlive) {
 | 
			
		||||
                    response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, file.length())
 | 
			
		||||
                    response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE)
 | 
			
		||||
                }
 | 
			
		||||
                ctx.write(response)
 | 
			
		||||
                ctx.write(new DefaultFileRegion(raf.getChannel(), 0, raf.length()))
 | 
			
		||||
                let future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT)
 | 
			
		||||
                if (!keepAlive) {
 | 
			
		||||
                    future.addListener(ChannelFutureListener.CLOSE)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user