├── .gitignore ├── .jshintrc ├── LICENSE.md ├── README.md ├── README_zh_CN.md ├── example ├── chat │ ├── chat.html │ ├── chat_server.js │ ├── css │ │ ├── bootstrap.min.css │ │ └── style.css │ └── js │ │ └── hprose-html5.js ├── client.js ├── client2.js ├── co │ ├── awaitexam2.js │ ├── awaitexam3.js │ ├── exam1.js │ ├── exam10.js │ ├── exam11.js │ ├── exam12.js │ ├── exam13.js │ ├── exam14.js │ ├── exam15.js │ ├── exam2.js │ ├── exam3.js │ ├── exam4.js │ ├── exam5.js │ ├── exam6.js │ ├── exam7.js │ ├── exam8.js │ └── exam9.js ├── connectserver.js ├── crossdomain.xml ├── expressserver.js ├── filter │ ├── compress │ │ ├── CompressFilter.js │ │ ├── SizeFilter.js │ │ ├── client.js │ │ ├── server.js │ │ └── statfilter.js │ └── log │ │ ├── client.js │ │ ├── logfilter.js │ │ └── server.js ├── future.js ├── httpclient.js ├── httpserver.js ├── jsonrpcclient.js ├── jsonrpcserver.js ├── middleware │ ├── batchlog │ │ ├── batchloghandler.js │ │ ├── client.js │ │ ├── loghandler.js │ │ └── server.js │ ├── cache │ │ ├── cachehandler.js │ │ ├── client.js │ │ ├── loghandler.js │ │ └── server.js │ ├── compressCache │ │ ├── CompressFilter.js │ │ ├── cachehandler.js │ │ ├── client.js │ │ ├── server.js │ │ ├── sizehandler.js │ │ └── stathandler.js │ ├── log │ │ ├── client.js │ │ ├── loghandler.js │ │ └── server.js │ └── log2 │ │ ├── client.js │ │ ├── loghandler.js │ │ └── server.js ├── proxyclient.js ├── proxyserver.js ├── serialize.js ├── server.js ├── server2.js ├── tcpclient.js ├── tcpclient2.js ├── tcpclient3.js ├── tcpclient4.js ├── tcpserver.js ├── testco.js ├── testthunkify.js ├── timeclient.js ├── timeoutclient.js ├── timeoutserver.js ├── timeserver.js ├── unixclient.js ├── unixserver.js ├── ws_client.js ├── wsclient.js └── wsserver.js ├── lib ├── client │ ├── Client.js │ ├── HttpClient.js │ ├── SocketClient.js │ └── WebSocketClient.js ├── common │ ├── Future.js │ ├── HarmonyMaps.js │ ├── Helper.js │ ├── Polyfill.js │ ├── ResultMode.js │ ├── TimeoutError.js │ └── isError.js ├── filter │ ├── JSONRPCClientFilter.js │ └── JSONRPCServiceFilter.js ├── hprose.js ├── io │ ├── BytesIO.js │ ├── ClassManager.js │ ├── Formatter.js │ ├── Reader.js │ ├── Tags.js │ └── Writer.js ├── server │ ├── HttpServer.js │ ├── HttpService.js │ ├── Server.js │ ├── Service.js │ ├── SocketServer.js │ ├── SocketService.js │ ├── WebSocketServer.js │ └── WebSocketService.js └── utils │ └── regenerator-runtime.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node":true, 3 | "sub":true, 4 | "laxbreak":true, 5 | "laxcomma":true, 6 | "regexp":true, 7 | "asi": true, 8 | "browser": true, 9 | "loopfunc":true, 10 | "expr":true, 11 | "es3": true, 12 | "esnext": true, 13 | "curly": true, 14 | "immed": true, 15 | "latedef": false, 16 | "expr": true, 17 | "eqeqeq": false, 18 | "eqnull": false, 19 | "newcap": true, 20 | "noarg": true, 21 | "undef": true, 22 | "unused": true, 23 | "proto": true, 24 | "strict": false, 25 | "smarttabs": true 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2008-2018 http://hprose.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Hprose

2 | 3 | 4 | Promises/A+ logo 5 | 6 | 7 | # Hprose for Node.js 8 | 9 | [![Join the chat at https://gitter.im/hprose/hprose-nodejs](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/hprose/hprose-nodejs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 10 | [![npm download](https://img.shields.io/npm/dm/hprose.svg)](https://www.npmjs.com/package/hprose) 11 | [![optionalDependency Status](https://david-dm.org/hprose/hprose-nodejs/optional-status.svg)](https://david-dm.org/hprose/hprose-nodejs#info=optionalDependencies) 12 | [![npm version](https://img.shields.io/npm/v/hprose.svg)](https://www.npmjs.com/package/hprose) 13 | [![License](https://img.shields.io/npm/l/hprose.svg)](http://opensource.org/licenses/MIT) 14 | 15 | >--- 16 | - **[Introduction](#introduction)** 17 | - **[Usage](#usage)** 18 | - **[Http Server](#http-server)** 19 | - [Synchronous Functions or Methods](#synchronous-functions-or-methods) 20 | - [Asynchronous Functions or Methods](#asynchronous-functions-or-methods) 21 | - **[Http Client](#http-client)** 22 | - [Exception Handling](#exception-handling) 23 | - **[Tcp Server & Client](#tcp-server-client)** 24 | - **[Unix Socket Server & Client](#unix-socket-server-client)** 25 | - **[WebSocket Server & Client](#websocket-server-client)** 26 | 27 | >--- 28 | 29 | ## Introduction 30 | 31 | *Hprose* is a High Performance Remote Object Service Engine. 32 | 33 | It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system. 34 | 35 | *Hprose* supports many programming languages, for example: 36 | 37 | * AAuto Quicker 38 | * ActionScript 39 | * ASP 40 | * C++ 41 | * Dart 42 | * Delphi/Free Pascal 43 | * dotNET(C#, Visual Basic...) 44 | * Golang 45 | * Java 46 | * JavaScript 47 | * Node.js 48 | * Objective-C 49 | * Perl 50 | * PHP 51 | * Python 52 | * Ruby 53 | * ... 54 | 55 | Through *Hprose*, You can conveniently and efficiently intercommunicate between those programming languages. 56 | 57 | This project is the implementation of Hprose for Node.js. 58 | 59 | Hprose 2.0 for Node.js Documents(中文版): https://github.com/hprose/hprose-nodejs/wiki 60 | 61 | ## Usage 62 | 63 | ### Http Server 64 | 65 | #### Synchronous Functions or Methods 66 | 67 | Hprose for Node.js is very easy to use. You can create a hprose server like this: 68 | 69 | ```javascript 70 | var hprose = require("hprose"); 71 | function hello(name) { 72 | return "Hello " + name + "!"; 73 | } 74 | var server = hprose.Server.create("http://0.0.0.0:8080"); 75 | server.addFunction(hello); 76 | server.start(); 77 | ``` 78 | 79 | To start it use: 80 | 81 | node --harmony server.js 82 | 83 | --harmony is a v8 options, hprose use it to optimize serialization. 84 | This is not required option, but it is recommended to use it. 85 | 86 | #### Asynchronous Functions or Methods 87 | 88 | In fact most nodejs service methods are asynchronous, you can publish asynchronous function like this: 89 | 90 | ```javascript 91 | var hprose = require("hprose"); 92 | function hello(name, callback) { 93 | setTimeout(function() { 94 | callback("Hello " + name + "!"); 95 | }, 10); 96 | } 97 | var server = hprose.Server.create("http://0.0.0.0:8080"); 98 | server.addAsyncFunction(hello); 99 | server.start(); 100 | ``` 101 | 102 | ### Http Client 103 | 104 | Then you can create a hprose client to invoke it like this: 105 | 106 | ```javascript 107 | var hprose = require("hprose"); 108 | var client = hprose.Client.create("http://127.0.0.1:8080/"); 109 | var proxy = client.useService(); 110 | proxy.hello("world", function(result) { 111 | console.log(result); 112 | }); 113 | ``` 114 | 115 | To start it use: 116 | 117 | node --harmony client.js 118 | 119 | or 120 | 121 | node --harmony-proxies client.js 122 | 123 | Without --harmony-proxies, you need create proxy like this: 124 | 125 | ```javascript 126 | var hprose = require("hprose"); 127 | var client = hprose.Client.create("http://127.0.0.1:8080/"); 128 | var proxy = client.useService(["hello"]); 129 | proxy.hello("world", function(result) { 130 | console.log(result); 131 | }); 132 | ``` 133 | 134 | Or create client like this: 135 | 136 | ```javascript 137 | var hprose = require("hprose"); 138 | var client = hprose.Client.create("http://127.0.0.1:8080/", ["hello"]); 139 | client.hello("world", function(result) { 140 | console.log(result); 141 | }); 142 | ``` 143 | 144 | #### Exception Handling 145 | 146 | If an error occurred on the server, or your service function/method throw an exception, it will be sent to the client. You need to pass an error callback function after succuss callback function to receive it. If you omit this callback function, the client will ignore the exception, like never happened. 147 | 148 | For example: 149 | 150 | ```javascript 151 | proxy.hello("world", function(result) { 152 | console.log(result); 153 | }, function(name, err) { 154 | console.error(err); 155 | }); 156 | ``` 157 | 158 | ### Tcp Server & Client 159 | 160 | The Tcp Server & Client are used as same as the Http Server & Client. 161 | 162 | To create a Tcp Server: 163 | 164 | ```javascript 165 | var server = hprose.Server.create("tcp://0.0.0.0:4321"); 166 | ``` 167 | 168 | To create a Tcp Client: 169 | 170 | ```javascript 171 | var client = hprose.Client.create('tcp://127.0.0.1:4321'); 172 | ``` 173 | 174 | ### Unix Socket Server & Client 175 | 176 | The Unix Socket Server & Client are used as same as the Http Server & Client. 177 | 178 | To create a Unix Socket Server: 179 | 180 | ```javascript 181 | var server = hprose.Server.create("unix:/tmp/my.sock"); 182 | ``` 183 | 184 | To create a Unix Socket Client: 185 | 186 | ```javascript 187 | var client = hprose.Client.create('unix:/tmp/my.sock'); 188 | ``` 189 | 190 | ### WebSocket Server & Client 191 | 192 | The WebSocket Server & Client are used as same as the Http Server & Client. 193 | 194 | To create a WebSocket Server: 195 | 196 | ```javascript 197 | var server = hprose.Server.create("ws://0.0.0.0:8080/"); 198 | ``` 199 | 200 | To create a WebSocket Client: 201 | 202 | ```javascript 203 | var client = hprose.Client.create('ws://0.0.0.0:8080/'); 204 | ``` 205 | -------------------------------------------------------------------------------- /README_zh_CN.md: -------------------------------------------------------------------------------- 1 |

Hprose

2 | 3 | 4 | Promises/A+ logo 5 | 6 | 7 | # Hprose for Node.js 8 | 9 | [![Join the chat at https://gitter.im/hprose/hprose-nodejs](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/hprose/hprose-nodejs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 10 | [![npm download](https://img.shields.io/npm/dm/hprose.svg)](https://www.npmjs.com/package/hprose) 11 | [![optionalDependency Status](https://david-dm.org/hprose/hprose-nodejs/optional-status.svg)](https://david-dm.org/hprose/hprose-nodejs#info=optionalDependencies) 12 | [![npm version](https://img.shields.io/npm/v/hprose.svg)](https://www.npmjs.com/package/hprose) 13 | [![License](https://img.shields.io/npm/l/hprose.svg)](http://opensource.org/licenses/MIT) 14 | 15 | >--- 16 | - **[简介](#简介)** 17 | - **[使用](#使用)** 18 | - **[Http 服务器](#http-服务器)** 19 | - [同步函数或方法](#同步函数或方法) 20 | - [异步函数或方法](#异步函数或方法) 21 | - **[Http 客户端](#http-客户端)** 22 | - [异常处理](#异常处理) 23 | - **[Tcp 服务器与客户端](#tcp-服务器与客户端)** 24 | - **[Unix Socket 服务器与客户端](#unix-socket-服务器与客户端)** 25 | - **[WebSocket 服务器与客户端](#websocket-服务器与客户端)** 26 | 27 | >--- 28 | 29 | ## 简介 30 | 31 | *Hprose* 是高性能远程对象服务引擎(High Performance Remote Object Service Engine)的缩写。 32 | 33 | 它是一个先进的轻量级的跨语言跨平台面向对象的高性能远程动态通讯中间件。它不仅简单易用,而且功能强大。你只需要稍许的时间去学习,就能用它轻松构建跨语言跨平台的分布式应用系统了。 34 | 35 | *Hprose* 支持众多编程语言,例如: 36 | 37 | * AAuto Quicker 38 | * ActionScript 39 | * ASP 40 | * C++ 41 | * Dart 42 | * Delphi/Free Pascal 43 | * dotNET(C#, Visual Basic...) 44 | * Golang 45 | * Java 46 | * JavaScript 47 | * Node.js 48 | * Objective-C 49 | * Perl 50 | * PHP 51 | * Python 52 | * Ruby 53 | * ... 54 | 55 | 通过 *Hprose*,你就可以在这些语言之间方便高效的实现互通了。 56 | 57 | 本项目是 Hprose 的 Node.js 语言版本实现。 58 | 59 | 更多 Hprose 2.0 for Node.js 文档: https://github.com/hprose/hprose-nodejs/wiki 60 | 61 | ## 使用 62 | 63 | ### Http 服务器 64 | 65 | #### 同步函数或方法 66 | 67 | Hprose for Node.js 使用很简单。你可用像这样创建 Hprose 服务器: 68 | 69 | ```javascript 70 | var hprose = require("hprose"); 71 | function hello(name) { 72 | return "Hello " + name + "!"; 73 | } 74 | var server = hprose.Server.create("http://0.0.0.0:8080"); 75 | server.addFunction(hello); 76 | server.start(); 77 | ``` 78 | 79 | 启动使用下面的命令: 80 | 81 | node --harmony server.js 82 | 83 | --harmony 是 v8 的一个选项,Hprose 使用该选项对序列化进行了优化。它不是必须的选项,但是建议使用它。 84 | 85 | #### 异步函数或方法 86 | 87 | 事实上,大多数 Node.js 服务是异步的,你可以像这样来发布异步函数或方法: 88 | 89 | ```javascript 90 | var hprose = require("hprose"); 91 | function hello(name, callback) { 92 | setTimeout(function() { 93 | callback("Hello " + name + "!"); 94 | }, 10); 95 | } 96 | var server = hprose.Server.create("http://0.0.0.0:8080"); 97 | server.addAsyncFunction(hello); 98 | server.start(); 99 | ``` 100 | 101 | ### Http 客户端 102 | 103 | 然后你可用创建 Hprose 客户端像这样来调用它: 104 | 105 | ```javascript 106 | var hprose = require("hprose"); 107 | var client = hprose.Client.create("http://127.0.0.1:8080/"); 108 | var proxy = client.useService(); 109 | proxy.hello("world", function(result) { 110 | console.log(result); 111 | }); 112 | ``` 113 | 114 | 使用如下命令启动它: 115 | 116 | node --harmony client.js 117 | 118 | 或者 119 | 120 | node --harmony-proxies client.js 121 | 122 | 如果没有 --harmony-proxies 参数,你需要这样创建远程调用代理对象: 123 | 124 | ```javascript 125 | var hprose = require("hprose"); 126 | var client = hprose.Client.create("http://127.0.0.1:8080/"); 127 | var proxy = client.useService(["hello"]); 128 | proxy.hello("world", function(result) { 129 | console.log(result); 130 | }); 131 | ``` 132 | 133 | 或者像这样创建客户端: 134 | 135 | ```javascript 136 | var hprose = require("hprose"); 137 | var client = hprose.Client.create("http://127.0.0.1:8080/", ["hello"]); 138 | client.hello("world", function(result) { 139 | console.log(result); 140 | }); 141 | ``` 142 | 143 | #### 异常处理 144 | 145 | 如果服务器端发生错误,或者你的服务函数或方法抛出了异常,它将被发送到客户端。你可以在成功回调函数后面传入错误回调函数来接收它。如果你忽略该回调函数,客户端将忽略该异常,就像从来没发生过一样。 146 | 147 | 例如: 148 | 149 | ```javascript 150 | proxy.hello("world", function(result) { 151 | console.log(result); 152 | }, function(name, err) { 153 | console.error(err); 154 | }); 155 | ``` 156 | 157 | ### Tcp 服务器与客户端 158 | 159 | Tcp 服务器与客户端的使用跟 Http 服务器与客户端是一样的。 160 | 161 | 创建一个 Tcp 服务器: 162 | 163 | ```javascript 164 | var server = hprose.Server.create("tcp://0.0.0.0:4321"); 165 | ``` 166 | 167 | 创建一个 Tcp 客户端: 168 | 169 | ```javascript 170 | var client = hprose.Client.create('tcp://127.0.0.1:4321'); 171 | ``` 172 | ### Unix Socket 服务器与客户端 173 | 174 | Unix Socket 服务器与客户端的使用跟 Http 服务器与客户端是一样的。 175 | 176 | 创建一个 Unix Socket 服务器: 177 | 178 | ```javascript 179 | var server = hprose.Server.create("unix:/tmp/my.sock"); 180 | ``` 181 | 182 | 创建一个 Unix Socket 客户端: 183 | 184 | ```javascript 185 | var client = hprose.Client.create('unix:/tmp/my.sock'); 186 | ``` 187 | 188 | ### WebSocket 服务器与客户端 189 | 190 | WebSocket 服务器与客户端的使用跟 Http 服务器与客户端是一样的。 191 | 192 | 创建一个 WebSocket 服务器: 193 | 194 | ```javascript 195 | var server = hprose.Server.create("ws://0.0.0.0:8080/"); 196 | ``` 197 | 198 | 创建一个 WebSocket 客户端: 199 | 200 | ```javascript 201 | var client = hprose.Client.create('ws://0.0.0.0:8080/'); 202 | ``` 203 | 204 | 更多详细文档请参见:[Hprose for Node.js 用户手册](https://github.com/hprose/hprose-nodejs/wiki) 205 | -------------------------------------------------------------------------------- /example/chat/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | chat 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 21 | 22 |
23 |
24 |
25 |
26 |
27 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /example/chat/chat_server.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../../lib/hprose.js'); 5 | var EventEmitter = require('events').EventEmitter; 6 | 7 | function Chat() {} 8 | 9 | var onlineChecker = new EventEmitter(); 10 | 11 | onlineChecker.on('subscribe', function(id, clients) { 12 | clients.push('message', id + ' is online.'); 13 | clients.push('updateUsers', clients.idlist('message')); 14 | }); 15 | 16 | onlineChecker.on('unsubscribe', function(id, clients) { 17 | clients.push('message', id + ' is offline.'); 18 | clients.push('updateUsers', clients.idlist('message')); 19 | }); 20 | 21 | Chat.prototype.getAllUsers = function(context) { 22 | return context.clients.idlist('message'); 23 | }; 24 | 25 | Chat.prototype.sendMessage = function(from, to, message, context) { 26 | context.clients.push('message', to, from + ' talk to me: ' + message); 27 | context.clients.push('message', from, 'I talk to ' + to + ': ' + message); 28 | }; 29 | 30 | Chat.prototype.broadcast = function(from, message, context) { 31 | context.clients.push('message', from + ' said: ' + message); 32 | }; 33 | 34 | function LogFilter() { 35 | this.inputFilter = function(value) { 36 | console.log(hprose.BytesIO.toString(value)); 37 | return value; 38 | }; 39 | this.outputFilter = function(value) { 40 | console.log(hprose.BytesIO.toString(value)); 41 | return value; 42 | }; 43 | } 44 | 45 | var server = hprose.Server.create("ws://0.0.0.0:8080"); 46 | server.debug = true; 47 | server.passContext = true; 48 | server.filter = new LogFilter(); 49 | var chat = new Chat(); 50 | server.addMethod('getAllUsers', chat); 51 | server.addMethods(['sendMessage', 'broadcast'], chat, { oneway: true }); 52 | server.publish('message', { events: onlineChecker }); 53 | server.publish('updateUsers'); 54 | server.on('sendError', function(e) { 55 | console.log(e.stack); 56 | }); 57 | server.start(); 58 | -------------------------------------------------------------------------------- /example/chat/css/style.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | background:#FCFCFC; 4 | } 5 | .say-btn 6 | { 7 | text-align:right; 8 | margin-top:12px; 9 | } 10 | 11 | #dialog 12 | { 13 | min-height:600px; 14 | background:#EEEEEE; 15 | } 16 | 17 | .textarea 18 | { 19 | height:6em; 20 | width:100%; 21 | } 22 | 23 | .words 24 | { 25 | margin:8px; 26 | } 27 | 28 | 29 | .triangle-isosceles { 30 | position:relative; 31 | padding:10px; 32 | margin:10px 0 15px; 33 | color:#000; 34 | background:#D3FF93; /* default background for browsers without gradient support */ 35 | background:-webkit-gradient(linear, 0 0, 0 100%, from(#EFFFD7), to(#D3FF93)); 36 | background:-moz-linear-gradient(#EFFFD7, #D3FF93); 37 | background:-o-linear-gradient(#EFFFD7, #D3FF93); 38 | background:linear-gradient(#EFFFD7, #D3FF93); 39 | -webkit-border-radius:10px; 40 | -moz-border-radius:10px; 41 | border-radius:10px; 42 | -moz-box-shadow:1px 1px 2px hsla(0, 0%, 0%, 0.3); 43 | -webkit-box-shadow:1px 1px 2px hsla(0, 0%, 0%, 0.3); 44 | box-shadow:1px 1px 2px hsla(0, 0%, 0%, 0.3); 45 | } 46 | 47 | .triangle-isosceles:hover{ 48 | top:-2px; 49 | left:-2px; 50 | -moz-box-shadow:3px 3px 2px hsla(0, 0%, 0%, 0.3); 51 | -webkit-box-shadow:3px 3px 2px hsla(0, 0%, 0%, 0.3); 52 | box-shadow:3px 3px 2x hsla(0, 0%, 0%, 0.3); 53 | } 54 | 55 | .triangle-isosceles.top { 56 | background:-webkit-gradient(linear, 0 0, 0 100%, from(#D3FF93), to(#EFFFD7)); 57 | background:-moz-linear-gradient(#D3FF93, #EFFFD7); 58 | background:-o-linear-gradient(#D3FF93, #EFFFD7); 59 | background:linear-gradient(#D3FF93, #EFFFD7); 60 | } 61 | 62 | .triangle-isosceles:after { 63 | content:""; 64 | position:absolute; 65 | bottom:-9px; 66 | left:15px; 67 | border-width:9px 21px 0; 68 | border-style:solid; 69 | border-color:#D3FF93 transparent; 70 | display:block; 71 | width:0; 72 | } 73 | .triangle-isosceles.top:after { 74 | top:-9px; 75 | left:15px; 76 | bottom:auto; 77 | border-width:0 9px 9px; 78 | border-color:#D3FF93 transparent; 79 | } 80 | 81 | .thumbnail 82 | { 83 | border:1px solid #CCCCCC; 84 | } -------------------------------------------------------------------------------- /example/client.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('http://127.0.0.1:8080/', []); 6 | client.simple = true; 7 | client.on('error', function(func, e) { 8 | console.log(func, e); 9 | }); 10 | var proxy = client.useService(['hello', 'hello2', 'getMaps']); 11 | var start = new Date().getTime(); 12 | var max = 100; 13 | var n = 0; 14 | client.subscribe('news', function(result) { 15 | console.log(result); 16 | }); 17 | var callback = function(result) { 18 | console.log(result); 19 | n++; 20 | if (n === max) { 21 | var end = new Date().getTime(); 22 | console.log(end - start); 23 | } 24 | }; 25 | for (var i = 0; i < max; i++) { 26 | proxy.hello(i, callback); 27 | } 28 | var end = new Date().getTime(); 29 | console.log(end - start); 30 | 31 | (async function() { 32 | console.log(await proxy.hello2("async world")); 33 | })(); 34 | 35 | client.batch.begin(); 36 | proxy.getMaps('name', 'age', 'age', function(result) { 37 | console.log(result); 38 | }); 39 | proxy.getMaps('name', 'age', 'birthday', function(result) { 40 | console.log(hprose.BytesIO.toString(result)); 41 | console.log(hprose.unserialize(result)); 42 | console.log(hprose.serialize(hprose.unserialize(result)).toString()); 43 | }, hprose.Serialized); 44 | client.batch.end(); 45 | proxy.hello("world", function(){ 46 | throw "Hello Error - 1!"; 47 | },function(name, err){ 48 | console.error("Error:", err); 49 | }); 50 | proxy.hello("world", function(){ 51 | throw "Hello Error - 2!"; 52 | }).catchError(function(err){ 53 | console.error("Error:", err); 54 | }); 55 | proxy.hello("world").then(function(){ 56 | throw "Hello Error - 3!"; 57 | }).catchError(function(err){ 58 | console.error("Error:", err); 59 | }); 60 | proxy.hello("world").then(function(){ 61 | throw "Hello Error - 4!"; 62 | },function(err){ 63 | console.error("Error:", err); // must not run 64 | }); 65 | -------------------------------------------------------------------------------- /example/client2.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('http://127.0.0.1:8080/', []); 6 | 7 | //client.simple = true; 8 | client.on('error', function(func, e) { 9 | console.log(func, e); 10 | }); 11 | var proxy = client.useService(['getUser']); 12 | proxy.getUser(); -------------------------------------------------------------------------------- /example/co/awaitexam2.js: -------------------------------------------------------------------------------- 1 | (async function() { 2 | try { 3 | console.log(await Promise.resolve("promise")); 4 | console.log(await function *() { return "generator" }); 5 | console.log(await new Date()); 6 | console.log(await 123); 7 | console.log(await 3.14); 8 | console.log(await "hello"); 9 | console.log(await true); 10 | } 11 | catch (e) { 12 | console.error(e); 13 | } 14 | })(); 15 | -------------------------------------------------------------------------------- /example/co/awaitexam3.js: -------------------------------------------------------------------------------- 1 | (async function() { 2 | try { 3 | var a = []; 4 | for (i = 0; i < 1000000; i++) { 5 | a[i] = i; 6 | } 7 | var start = Date.now(); 8 | await a; 9 | var end = Date.now(); 10 | console.log(end - start); 11 | } 12 | catch (e) { 13 | console.error(e); 14 | } 15 | })(); 16 | 17 | (async function() { 18 | try { 19 | var a = []; 20 | a[0] = a; 21 | console.log(await a); 22 | } 23 | catch (e) { 24 | console.error(e); 25 | } 26 | })(); 27 | 28 | (async function() { 29 | try { 30 | var o = {}; 31 | o.self = o; 32 | console.log(await o); 33 | } 34 | catch (e) { 35 | console.error(e); 36 | } 37 | })(); 38 | -------------------------------------------------------------------------------- /example/co/exam1.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | hprose.co(function*() { 4 | var client = hprose.Client.create('http://hprose.com/example/'); 5 | yield client.useService(); 6 | console.log(yield client.hello("World")); 7 | }); 8 | -------------------------------------------------------------------------------- /example/co/exam10.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | 4 | var coroutine = hprose.wrap(function*(client) { 5 | console.log(1); 6 | console.log((yield client.hello("hprose"))); 7 | var a = client.sum(1, 2, 3); 8 | var b = client.sum(4, 5, 6); 9 | var c = client.sum(7, 8, 9); 10 | console.log((yield client.sum(a, b, c))); 11 | console.log((yield client.hello("world"))); 12 | }); 13 | 14 | hprose.co(function*() { 15 | var client = hprose.Client.create('http://hprose.com/example/'); 16 | yield client.useService(); 17 | coroutine(client); 18 | coroutine(Promise.resolve(client)); 19 | }); 20 | -------------------------------------------------------------------------------- /example/co/exam11.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | hprose.co(function*() { 4 | var client = hprose.Client.create('http://hprose.com/example/'); 5 | try { 6 | console.log(yield client.invoke('ooxx')); 7 | } 8 | catch (e) { 9 | console.log(e.message); 10 | } 11 | }); -------------------------------------------------------------------------------- /example/co/exam12.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | hprose.co(function*() { 4 | var client = hprose.Client.create('http://hprose.com/example/'); 5 | console.log(yield client.invoke('oo')); 6 | console.log(yield client.invoke('xx')); 7 | }).catch(function(e) { 8 | console.log(e.message); 9 | }); -------------------------------------------------------------------------------- /example/co/exam13.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | hprose.co(function*() { 4 | var client = hprose.Client.create('http://hprose.com/example/'); 5 | console.log(yield client.invoke('oo').complete()); 6 | console.log(yield client.invoke('xx').complete()); 7 | }); -------------------------------------------------------------------------------- /example/co/exam14.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | function sum(a, b, callback) { 4 | callback(a + b); 5 | } 6 | 7 | var sum1 = hprose.promisify(sum); 8 | var sum2 = hprose.thunkify(sum); 9 | 10 | sum1(1, 2).then(function(result) { 11 | console.log(result); 12 | }); 13 | 14 | sum2(2, 3)(function(result) { 15 | console.log(result); 16 | }); 17 | 18 | hprose.co(function*() { 19 | console.log(yield sum1(3, 4)); 20 | console.log(yield sum2(4, 5)); 21 | }); 22 | 23 | (async function() { 24 | console.log(await sum1(5, 6)); 25 | console.log(await sum2(6, 7)); 26 | })(); -------------------------------------------------------------------------------- /example/co/exam15.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | function normal(p) { 4 | console.log(p); 5 | return normal; 6 | } 7 | 8 | function* coroutine(p) { 9 | console.log(yield p); 10 | return coroutine; 11 | } 12 | 13 | // hprose.co(function*() { 14 | // var p = Promise.resolve(123); 15 | // console.log(normal(p)); 16 | // console.log(yield coroutine(p)); 17 | // }) 18 | 19 | function* run(fn) { 20 | var p = Promise.resolve(123); 21 | console.log(yield hprose.Future.toPromise(fn(p))); 22 | } 23 | 24 | hprose.co(function*() { 25 | yield run(normal); 26 | yield run(coroutine); 27 | }); -------------------------------------------------------------------------------- /example/co/exam2.js: -------------------------------------------------------------------------------- 1 | var co = require('hprose').co; 2 | 3 | co(function*() { 4 | try { 5 | console.log(yield Promise.resolve("promise")); 6 | console.log(yield function *() { return "generator" }); 7 | console.log(yield new Date()); 8 | console.log(yield 123); 9 | console.log(yield 3.14); 10 | console.log(yield "hello"); 11 | console.log(yield true); 12 | } 13 | catch (e) { 14 | console.error(e); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /example/co/exam3.js: -------------------------------------------------------------------------------- 1 | var co = require('hprose').co; 2 | 3 | co(function*() { 4 | try { 5 | var a = []; 6 | for (i = 0; i < 1000000; i++) { 7 | a[i] = i; 8 | } 9 | var start = Date.now(); 10 | yield a; 11 | var end = Date.now(); 12 | console.log(end - start); 13 | } 14 | catch (e) { 15 | console.error(e); 16 | } 17 | }); 18 | 19 | co(function*() { 20 | try { 21 | var a = []; 22 | a[0] = a; 23 | console.log(yield a); 24 | } 25 | catch (e) { 26 | console.error(e); 27 | } 28 | }); 29 | 30 | co(function*() { 31 | try { 32 | var o = {}; 33 | o.self = o; 34 | console.log(yield o); 35 | } 36 | catch (e) { 37 | console.error(e); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /example/co/exam4.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var co = hprose.co; 3 | var thunkify = hprose.thunkify; 4 | 5 | var sum = thunkify(function(a, b, callback) { 6 | console.log("call sum(" + Array.prototype.join.call(arguments) + ")"); 7 | callback(null, a + b); 8 | callback(null, a + b + a); 9 | }); 10 | 11 | co(function*() { 12 | var result = sum(1, 2); 13 | console.log(yield result); 14 | console.log(yield sum(2, 3)); 15 | console.log(yield result); 16 | }); 17 | -------------------------------------------------------------------------------- /example/co/exam5.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var co = hprose.co; 3 | var thunkify = hprose.thunkify; 4 | 5 | var sum = thunkify(function(a, b, callback) { 6 | callback(a + b); 7 | }); 8 | 9 | co(function*() { 10 | var result = sum(1, 2); 11 | console.log(yield result); 12 | console.log(yield sum(2, 3)); 13 | console.log(yield result); 14 | }); 15 | -------------------------------------------------------------------------------- /example/co/exam6.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | hprose.co(function*() { 4 | var client = hprose.Client.create('http://hprose.com/example/'); 5 | yield client.useService(); 6 | console.log(yield client.hello("Hprose")); 7 | var a = client.sum(1, 2, 3); 8 | var b = client.sum(4, 5, 6); 9 | var c = client.sum(7, 8, 9); 10 | console.log(yield client.sum(a, b, c)); 11 | console.log(yield client.hello("World")); 12 | }); 13 | -------------------------------------------------------------------------------- /example/co/exam7.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | var client = hprose.Client.create('http://hprose.com/example/'); 4 | var proxy = client.useService(); 5 | 6 | hprose.co(function*() { 7 | var client = yield proxy; 8 | for (var i = 0; i < 5; i++) { 9 | console.log((yield client.hello("1-" + i))); 10 | } 11 | }); 12 | 13 | hprose.co(function*() { 14 | var client = yield proxy; 15 | for (var i = 0; i < 5; i++) { 16 | console.log((yield client.hello("2-" + i))); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /example/co/exam8.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | function *hello(n, client) { 4 | var result = []; 5 | for (var i = 0; i < 5; i++) { 6 | result[i] = client.hello(n + "-" + i); 7 | } 8 | return Promise.all(result); 9 | } 10 | 11 | hprose.co(function*() { 12 | var client = hprose.Client.create('http://hprose.com/example/'); 13 | yield client.useService(); 14 | var result = yield hprose.co(function *(client) { 15 | var result = []; 16 | for (var i = 0; i < 3; i++) { 17 | result[i] = hprose.co(hello, i, client); 18 | } 19 | return Promise.all(result); 20 | }, client); 21 | console.log(result); 22 | }); 23 | -------------------------------------------------------------------------------- /example/co/exam9.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | 3 | hprose.co(function*() { 4 | var client = hprose.Client.create('http://hprose.com/example/'); 5 | yield client.useService(); 6 | for (var i = 0; i < 5; i++) { 7 | console.log(yield client.hello("1-" + i)); 8 | } 9 | var console_log = hprose.wrap(console.log, console); 10 | for (var i = 0; i < 5; i++) { 11 | console_log(client.hello("2-" + i)); 12 | } 13 | for (var i = 0; i < 5; i++) { 14 | console.log(yield client.hello("3-" + i)); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /example/connectserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var connect = require('connect'); 6 | var session = require('cookie-session'); 7 | 8 | function hello(name, context) { 9 | context.clients.push("news", "this is a pushed message: " + name); 10 | context.clients.broadcast("news", {x: 1, y: 2, message: "this is a pushed object:" + name}); 11 | return 'Hello ' + name + '! -- ' + context.socket.remoteAddress; 12 | } 13 | 14 | function hello2(name) { 15 | return 'Hello ' + name + '!'; 16 | } 17 | 18 | function asyncHello(name, callback) { 19 | callback('Hello ' + name + '!'); 20 | } 21 | 22 | function getMaps() { 23 | var context = Array.prototype.pop.call(arguments); 24 | var result = {}; 25 | var key; 26 | for (key in arguments) { 27 | result[key] = arguments[key]; 28 | } 29 | return result; 30 | } 31 | 32 | function LogFilter() { 33 | this.inputFilter = function(value) { 34 | console.log(hprose.BytesIO.toString(value)); 35 | return value; 36 | }; 37 | this.outputFilter = function(value) { 38 | console.log(hprose.BytesIO.toString(value)); 39 | return value; 40 | }; 41 | } 42 | 43 | var server = new hprose.HttpService(); 44 | server.crossDomain = true; 45 | server.crossDomainXmlFile = './crossdomain.xml'; 46 | server.debug = true; 47 | server.filter = new LogFilter(); 48 | server.simple = true; 49 | server.passContext = true; 50 | server.addFunctions([hello, hello2, getMaps]); 51 | server.addAsyncFunction(asyncHello); 52 | server.publish('news'); 53 | server.on('sendError', function(message) { 54 | console.log(message); 55 | }); 56 | 57 | var app = connect() 58 | .use(session({ 59 | name: 'session', 60 | keys: ['key1', 'key2'] 61 | })) 62 | .use(server.handle) 63 | .listen(8080); 64 | -------------------------------------------------------------------------------- /example/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /example/expressserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var express = require('express'); 6 | var session = require('cookie-session'); 7 | 8 | function hello(name, context) { 9 | context.clients.push("news", "this is a pushed message: " + name); 10 | context.clients.broadcast("news", {x: 1, y: 2, message: "this is a pushed object:" + name}); 11 | return 'Hello ' + name + '! -- ' + context.socket.remoteAddress; 12 | } 13 | 14 | function hello2(name) { 15 | return 'Hello ' + name + '!'; 16 | } 17 | 18 | function asyncHello(name, callback) { 19 | callback('Hello ' + name + '!'); 20 | } 21 | 22 | function getMaps() { 23 | var context = Array.prototype.pop.call(arguments); 24 | var result = {}; 25 | var key; 26 | for (key in arguments) { 27 | result[key] = arguments[key]; 28 | } 29 | return result; 30 | } 31 | 32 | function LogFilter() { 33 | this.inputFilter = function(value) { 34 | console.log(hprose.BytesIO.toString(value)); 35 | return value; 36 | }; 37 | this.outputFilter = function(value) { 38 | console.log(hprose.BytesIO.toString(value)); 39 | return value; 40 | }; 41 | } 42 | 43 | var server = new hprose.HttpService(); 44 | server.crossDomain = true; 45 | server.crossDomainXmlFile = './crossdomain.xml'; 46 | server.debug = true; 47 | server.filter = new LogFilter(); 48 | server.simple = true; 49 | server.passContext = true; 50 | server.addFunctions([hello, hello2, getMaps]); 51 | server.addAsyncFunction(asyncHello); 52 | server.publish('news'); 53 | server.on('sendError', function(message) { 54 | console.log(message); 55 | }); 56 | 57 | var app = express() 58 | .use(session({ 59 | name: 'session', 60 | keys: ['key1', 'key2'] 61 | })) 62 | .use(server.handle) 63 | .listen(8080); 64 | -------------------------------------------------------------------------------- /example/filter/compress/CompressFilter.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | var compressjs = require('compressjs'); 3 | function CompressFilter(algorithmName) { 4 | this.algorithm = compressjs[algorithmName]; 5 | } 6 | CompressFilter.prototype.inputFilter = function(data) { 7 | return this.algorithm.decompressFile(data); 8 | }; 9 | CompressFilter.prototype.outputFilter = function(data) { 10 | return this.algorithm.compressFile(data); 11 | }; 12 | module.exports = CompressFilter; 13 | -------------------------------------------------------------------------------- /example/filter/compress/SizeFilter.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | function SizeFilter(message) { 3 | this.message = message; 4 | } 5 | SizeFilter.prototype.inputFilter = function(data) { 6 | console.log(this.message + ' input size: ' + data.length); 7 | return data; 8 | }; 9 | SizeFilter.prototype.outputFilter = function(data) { 10 | console.log(this.message + ' output size: ' + data.length); 11 | return data; 12 | }; 13 | module.exports = SizeFilter; 14 | -------------------------------------------------------------------------------- /example/filter/compress/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var CompressFilter = require("./CompressFilter.js"); 3 | var SizeFilter = require("./SizeFilter.js"); 4 | var statfilter = require("./statfilter.js"); 5 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['echo']); 6 | client.addFilter(statfilter); 7 | client.addFilter(new SizeFilter('Non compressed')); 8 | client.addFilter(new CompressFilter('Lzp3')); 9 | client.addFilter(new SizeFilter('Compressed')); 10 | client.addFilter(statfilter); 11 | var value = []; 12 | for (var i = 0; i < 100000; i++) { 13 | value[i] = i; 14 | } 15 | client.echo(value, function(result) { 16 | console.log(result.length); 17 | }); 18 | -------------------------------------------------------------------------------- /example/filter/compress/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var CompressFilter = require("./CompressFilter.js"); 3 | var SizeFilter = require("./SizeFilter.js"); 4 | var statfilter = require("./statfilter.js"); 5 | function echo(value) { 6 | return value; 7 | } 8 | var server = hprose.Server.create("http://0.0.0.0:8080"); 9 | server.addFunction(echo); 10 | server.addFilter(statfilter); 11 | server.addFilter(new SizeFilter('Non compressed')); 12 | server.addFilter(new CompressFilter('Lzp3')); 13 | server.addFilter(new SizeFilter('Compressed')); 14 | server.addFilter(statfilter); 15 | server.start(); 16 | -------------------------------------------------------------------------------- /example/filter/compress/statfilter.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | function stat(data, context) { 3 | if ('starttime' in context.userdata) { 4 | var t = Date.now() - context.userdata.starttime; 5 | console.log('It takes ' + t + ' ms.'); 6 | } 7 | else { 8 | context.userdata.starttime = Date.now(); 9 | } 10 | return data; 11 | } 12 | module.exports = { 13 | inputFilter: stat, 14 | outputFilter: stat 15 | }; 16 | -------------------------------------------------------------------------------- /example/filter/log/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var logfilter = require("./logfilter.js"); 3 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['hello']); 4 | client.addFilter(logfilter); 5 | client.hello("world", function(result) { 6 | console.log(result); 7 | }); 8 | -------------------------------------------------------------------------------- /example/filter/log/logfilter.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | function log(data) { 3 | console.log(hprose.BytesIO.toString(data)); 4 | return data; 5 | } 6 | module.exports = { 7 | inputFilter: log, 8 | outputFilter: log 9 | }; 10 | -------------------------------------------------------------------------------- /example/filter/log/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var logfilter = require("./logfilter.js"); 3 | function hello(name) { 4 | return "Hello " + name + "!"; 5 | } 6 | var server = hprose.Server.create("http://0.0.0.0:8080"); 7 | server.addFunction(hello); 8 | server.addFilter(logfilter); 9 | server.start(); 10 | -------------------------------------------------------------------------------- /example/future.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var TimeoutError = require('../lib/common/TimeoutError.js'); 6 | 7 | (function() { 8 | var completer = new hprose.Completer(); 9 | var future = completer.future; 10 | future.then(function(result) { 11 | return result + 1; 12 | }).then(function(result) { 13 | return result + 1; 14 | }).then(function(result) { 15 | console.log(result); 16 | }); 17 | future.then(function(result) { 18 | console.log(result); 19 | }); 20 | completer.complete(1); 21 | })(); 22 | 23 | (function() { 24 | var completer = new hprose.Completer(); 25 | var future = completer.future; 26 | future.then(null, function(result) { 27 | return result + 1; 28 | }).then(function(result) { 29 | return result + 1; 30 | }).then(function(result) { 31 | console.log(result); 32 | }); 33 | future.then(null, function(result) { 34 | console.log(result); 35 | }); 36 | completer.completeError(1); 37 | })(); 38 | 39 | (function() { 40 | var Future = hprose.Future; 41 | var p1 = Future.delayed(500, function() { return "one"; }); 42 | var p2 = Future.delayed(100, function() { return "two"; }); 43 | Future.race([p1, p2]).then(function(value) { 44 | console.log(value); 45 | }); 46 | Future.race([Future.resolve("p1"), "p2"]).then(function(value) { 47 | console.log(value); 48 | }); 49 | })(); 50 | 51 | (function() { 52 | var Future = hprose.Future; 53 | var p1 = Future.delayed(500, function() { return "one"; }); 54 | var p2 = Future.delayed(100, function() { return "two"; }); 55 | Future.any([p1, p2]).then(function(value) { 56 | console.log(value); 57 | }); 58 | Future.any([Future.resolve("p1"), "p2"]).then(function(value) { 59 | console.log(value); 60 | }); 61 | Future.any([Future.error(1), Future.error(2)]).then(null, function(value) { 62 | console.log(value); 63 | }); 64 | Future.any([]).then(null, function(value) { 65 | console.log(value); 66 | }); 67 | })(); 68 | 69 | (function() { 70 | var Future = hprose.Future; 71 | var promise = Future.resolve(3); 72 | Future.all([true, promise]).then(function(values) { 73 | console.log(values); // [true, 3] 74 | }); 75 | })(); 76 | 77 | (function() { 78 | var Future = hprose.Future; 79 | var promise = Future.resolve(3); 80 | Future.join(true, promise).then(function(values) { 81 | console.log(values); // [true, 3] 82 | }); 83 | })(); 84 | 85 | (function() { 86 | var Future = hprose.Future; 87 | var promise = Future.resolve(3); 88 | Future.settle([true, promise, Future.error('e')]).then(function(values) { 89 | console.log(values); // [true, 3] 90 | }); 91 | })(); 92 | 93 | (function() { 94 | var Future = hprose.Future; 95 | var promise = Future.resolve(3); 96 | console.log(promise.inspect()); // Object {state: "fulfilled", value: 3} 97 | })(); 98 | 99 | (function() { 100 | var Future = hprose.Future; 101 | var promise = Future.resolve(3); 102 | Future.forEach([true, promise], function(value) { 103 | console.log(value); 104 | }); 105 | // true 106 | // 3 107 | })(); 108 | 109 | (function() { 110 | var Future = hprose.Future; 111 | var promise = Future.resolve(3); 112 | Future.resolve([true, promise]).forEach(function(value) { 113 | console.log(value); 114 | }); 115 | // true 116 | // 3 117 | })(); 118 | 119 | (function() { 120 | var Future = hprose.Future; 121 | var promise = Future.resolve(3); 122 | Future.resolve([true, promise]).forEach(function(value) { 123 | console.log(value); 124 | }); 125 | // true 126 | // 3 127 | })(); 128 | 129 | (function() { 130 | var Future = hprose.Future; 131 | function add(a, b) { return a + b; } 132 | var a = Future.resolve(3); 133 | var b = Future.resolve(5); 134 | Future.run(console.log, console, Future.run(add, null, a, b)); // 8 135 | })(); 136 | 137 | (function() { 138 | var Future = hprose.Future; 139 | Future.delayed(500, function() { return "one"; }) 140 | .timeout(300) 141 | .then(function(value) { 142 | console.log(value); 143 | }) 144 | .catchError(function(reason) { 145 | console.error(reason); 146 | }, function(e) { 147 | return e instanceof TimeoutError; 148 | }); 149 | })(); 150 | 151 | (function() { 152 | var Future = hprose.Future; 153 | var delayedDate = Future.delayed(1000, function() { return new Date(); }); 154 | var log = Future.wrap(console.log, console); 155 | log(delayedDate); 156 | delayedDate.bind(Object.getOwnPropertyNames(Date.prototype)); 157 | log(delayedDate.getTime()); 158 | log(delayedDate.call('toLocaleString')); 159 | log(delayedDate.apply('toTimeString')); 160 | delayedDate.set('year', delayedDate.getFullYear()); 161 | log(delayedDate.get('year')); 162 | })(); 163 | 164 | (function() { 165 | var Promise = global.Promise; 166 | var promiseCount = 0; 167 | 168 | function testPromise() { 169 | var thisPromiseCount = ++promiseCount; 170 | 171 | console.log(thisPromiseCount + 172 | ') Started (Sync code started)'); 173 | 174 | // We make a new promise: we promise the string 'result' (after waiting 3s) 175 | var p1 = new Promise( 176 | // The resolver function is called with the ability to resolve or 177 | // reject the promise 178 | function(resolve, reject) { 179 | console.log(thisPromiseCount + 180 | ') Promise started (Async code started)'); 181 | // This only is an example to create asynchronism 182 | global.setTimeout( 183 | function() { 184 | // We fulfill the promise ! 185 | resolve(thisPromiseCount); 186 | }, Math.random() * 2000 + 1000); 187 | }); 188 | 189 | // We define what to do when the promise is fulfilled 190 | //but we only call this if the promise is resolved/fulfilled 191 | p1.then( 192 | // Just log the message and a value 193 | function(val) { 194 | console.log(val + 195 | ') Promise fulfilled (Async code terminated)'); 196 | }).catch(function() { console.log('promise was rejected');}); 197 | 198 | console.log(thisPromiseCount + 199 | ') Promise made (Sync code terminated)'); 200 | } 201 | 202 | testPromise(); 203 | testPromise(); 204 | testPromise(); 205 | testPromise(); 206 | })(); 207 | -------------------------------------------------------------------------------- /example/httpclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('http://127.0.0.1:8080/', []); 6 | client.simple = true; 7 | client.on('error', function(func, e) { 8 | console.log(func, e); 9 | }); 10 | hprose.co(function*() { 11 | var proxy = client.useService(['hello']); 12 | var start = new Date().getTime(); 13 | for (var i = 0; i < 100; i++) { 14 | var result = yield proxy.hello(i); 15 | console.log(result); 16 | } 17 | var end = new Date().getTime(); 18 | console.log("time: " + (end - start)); 19 | }); 20 | -------------------------------------------------------------------------------- /example/httpserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function* hello(name) { 7 | return 'Hello ' + name + '!'; 8 | } 9 | 10 | var server = hprose.Server.create("http://0.0.0.0:8080"); 11 | server.crossDomain = true; 12 | server.crossDomainXmlFile = './crossdomain.xml'; 13 | server.debug = true; 14 | server.addFunction(hello); 15 | server.on('sendError', function(message) { 16 | console.log(message.stack); 17 | }); 18 | process.on('SIGINT', function() { 19 | server.stop(); 20 | }); 21 | server.start(); 22 | -------------------------------------------------------------------------------- /example/jsonrpcclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('http://127.0.0.1:8080/', []); 6 | client.filter = new hprose.JSONRPCClientFilter(); 7 | client.simple = true; 8 | client.on('error', function(func, e) { 9 | console.log(func, e); 10 | }); 11 | var proxy = client.useService(['hello', 'hello2', 'getMaps']); 12 | var start = new Date().getTime(); 13 | var max = 10; 14 | var n = 0; 15 | var callback = function(result) { 16 | console.log(result); 17 | n++; 18 | if (n === max) { 19 | var end = new Date().getTime(); 20 | console.log(end - start); 21 | } 22 | }; 23 | client.batch.begin(); 24 | for (var i = 0; i < max; i++) { 25 | proxy.hello(i, callback); 26 | } 27 | var end = new Date().getTime(); 28 | console.log(end - start); 29 | proxy.getMaps('name', 'age', 'age', function(result) { 30 | console.log(result); 31 | }); 32 | proxy.getMaps('name', 'age', 'birthday', function(result) { 33 | console.log(hprose.BytesIO.toString(result)); 34 | console.log(hprose.unserialize(result)); 35 | console.log(hprose.serialize(hprose.unserialize(result)).toString()); 36 | }, hprose.Serialized); 37 | client.batch.end(); 38 | -------------------------------------------------------------------------------- /example/jsonrpcserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function hello(name, context) { 7 | return 'Hello ' + name + '! -- ' + context.socket.remoteAddress; 8 | } 9 | 10 | function hello2(name) { 11 | return 'Hello ' + name + '!'; 12 | } 13 | 14 | function asyncHello(name, callback) { 15 | callback('Hello ' + name + '!'); 16 | } 17 | 18 | function getMaps() { 19 | var context = Array.prototype.pop.call(arguments); 20 | var result = {}; 21 | var key; 22 | for (key in arguments) { 23 | result[key] = arguments[key]; 24 | } 25 | return result; 26 | } 27 | 28 | function LogFilter() { 29 | this.inputFilter = function(value) { 30 | console.log("request: " + hprose.BytesIO.toString(value)); 31 | return value; 32 | }; 33 | this.outputFilter = function(value) { 34 | console.log("resonpse: " + hprose.BytesIO.toString(value)); 35 | return value; 36 | }; 37 | } 38 | 39 | var server = hprose.Server.create("http://0.0.0.0:8080"); 40 | server.crossDomain = true; 41 | server.crossDomainXmlFile = './crossdomain.xml'; 42 | server.debug = true; 43 | server.addFilter(new hprose.JSONRPCServiceFilter()); 44 | server.addFilter(new LogFilter()); 45 | server.simple = true; 46 | server.passContext = true; 47 | server.addFunctions([hello, hello2, getMaps]); 48 | server.addAsyncFunction(asyncHello); 49 | server.on('sendError', function(message) { 50 | console.error(message.stack); 51 | }); 52 | process.on('SIGINT', function() { 53 | server.stop(); 54 | }); 55 | server.start(); 56 | -------------------------------------------------------------------------------- /example/middleware/batchlog/batchloghandler.js: -------------------------------------------------------------------------------- 1 | module.exports = function*(batches, context, next) { 2 | console.log("before invoke:", batches); 3 | var result = yield next(batches, context); 4 | console.log("after invoke:", batches, result); 5 | return result; 6 | }; 7 | -------------------------------------------------------------------------------- /example/middleware/batchlog/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var batchloghandler = require("./batchloghandler.js"); 3 | var log = hprose.Future.wrap(console.log, console); 4 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['hello']); 5 | client.batch.use(batchloghandler); 6 | client.batch.begin(); 7 | var r1 = client.hello("world 1"); 8 | var r2 = client.hello("world 2"); 9 | var r3 = client.hello("world 3"); 10 | client.batch.end(); 11 | log(r1, r2, r3); 12 | -------------------------------------------------------------------------------- /example/middleware/batchlog/loghandler.js: -------------------------------------------------------------------------------- 1 | module.exports = function*(name, args, context, next) { 2 | console.log("before invoke:", name, args); 3 | var result = yield next(name, args, context); 4 | console.log("after invoke:", name, args, result); 5 | return result; 6 | }; 7 | -------------------------------------------------------------------------------- /example/middleware/batchlog/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | function hello(name) { 4 | return "Hello " + name + "!"; 5 | } 6 | var server = hprose.Server.create("http://0.0.0.0:8080"); 7 | server.use(loghandler); 8 | server.add(hello); 9 | server.start(); 10 | -------------------------------------------------------------------------------- /example/middleware/cache/cachehandler.js: -------------------------------------------------------------------------------- 1 | var cache = {}; 2 | module.exports = function(name, args, context, next) { 3 | if (context.userdata.cache) { 4 | var key = JSON.stringify(args); 5 | if (name in cache) { 6 | if (key in cache[name]) { 7 | return cache[name][key]; 8 | } 9 | } 10 | else { 11 | cache[name] = {}; 12 | } 13 | var result = next(name, args, context); 14 | cache[name][key] = result; 15 | return result; 16 | } 17 | return next(name, args, context); 18 | }; 19 | -------------------------------------------------------------------------------- /example/middleware/cache/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | var cachehandler = require("./cachehandler.js"); 4 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['hello']); 5 | client.use(cachehandler) 6 | .use(loghandler); 7 | client.hello("cache world", function(result) { 8 | console.log(result); 9 | }, { userdata: { cache: true } }); 10 | client.hello("cache world", function(result) { 11 | console.log(result); 12 | }, { userdata: { cache: true } }); 13 | client.hello("no cache world", function(result) { 14 | console.log(result); 15 | }); 16 | client.hello("no cache world", function(result) { 17 | console.log(result); 18 | }); 19 | -------------------------------------------------------------------------------- /example/middleware/cache/loghandler.js: -------------------------------------------------------------------------------- 1 | module.exports = function*(name, args, context, next) { 2 | console.log("before invoke:", name, args); 3 | var result = yield next(name, args, context); 4 | console.log("after invoke:", name, args, result); 5 | return result; 6 | }; 7 | -------------------------------------------------------------------------------- /example/middleware/cache/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | function hello(name) { 4 | return "Hello " + name + "!"; 5 | } 6 | var server = hprose.Server.create("http://0.0.0.0:8080"); 7 | server.use(loghandler); 8 | server.add(hello); 9 | server.start(); 10 | -------------------------------------------------------------------------------- /example/middleware/compressCache/CompressFilter.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | var compressjs = require('compressjs'); 3 | function CompressFilter(algorithmName) { 4 | this.algorithm = compressjs[algorithmName]; 5 | } 6 | CompressFilter.prototype.inputFilter = function(data) { 7 | return this.algorithm.decompressFile(data); 8 | }; 9 | CompressFilter.prototype.outputFilter = function(data) { 10 | return this.algorithm.compressFile(data); 11 | }; 12 | module.exports = CompressFilter; 13 | -------------------------------------------------------------------------------- /example/middleware/compressCache/cachehandler.js: -------------------------------------------------------------------------------- 1 | var cache = {}; 2 | module.exports = function(request, context, next) { 3 | if (context.userdata.cache) { 4 | if (request in cache) { 5 | return cache[request]; 6 | } 7 | var response = next(request, context); 8 | cache[request] = response; 9 | return response; 10 | } 11 | return next(request, context); 12 | }; 13 | -------------------------------------------------------------------------------- /example/middleware/compressCache/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var CompressFilter = require("./CompressFilter.js"); 3 | var cachehandler = require("./cachehandler.js"); 4 | var sizehandler = require("./sizehandler.js"); 5 | var stathandler = require("./stathandler.js"); 6 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['echo']); 7 | client.beforeFilter.use(cachehandler) 8 | .use(stathandler('BeforeFilter')) 9 | .use(sizehandler('Non compressed')); 10 | client.addFilter(new CompressFilter('Lzp3')); 11 | client.afterFilter.use(stathandler('AfterFilter')) 12 | .use(sizehandler('compressed')); 13 | var value = []; 14 | for (var i = 0; i < 100000; i++) { 15 | value[i] = i; 16 | } 17 | client.echo(value, function(result) { 18 | console.log(result.length); 19 | }, { userdata: { cache: true } }); 20 | client.echo(value, function(result) { 21 | console.log(result.length); 22 | }, { userdata: { cache: true } }); 23 | -------------------------------------------------------------------------------- /example/middleware/compressCache/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var CompressFilter = require("./CompressFilter.js"); 3 | var sizehandler = require("./sizehandler.js"); 4 | var stathandler = require("./stathandler.js"); 5 | function echo(value) { 6 | return value; 7 | } 8 | var server = hprose.Server.create("http://0.0.0.0:8080"); 9 | server.beforeFilter.use(stathandler('BeforeFilter')) 10 | .use(sizehandler('compressed')); 11 | server.addFilter(new CompressFilter('Lzp3')); 12 | server.afterFilter.use(stathandler('AfterFilter')) 13 | .use(sizehandler('Non compressed')); 14 | server.add(echo); 15 | server.start(); 16 | -------------------------------------------------------------------------------- /example/middleware/compressCache/sizehandler.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | module.exports = function(message) { 3 | return function*(request, context, next) { 4 | console.log(message + ' request size: ' + request.length); 5 | var response = yield next(request, context); 6 | console.log(message + ' response size: ' + response.length); 7 | return response; 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /example/middleware/compressCache/stathandler.js: -------------------------------------------------------------------------------- 1 | module.exports = function(message) { 2 | return function*(request, context, next) { 3 | var start = Date.now(); 4 | var response = yield next(request, context); 5 | var end = Date.now(); 6 | console.log(message + ': It takes ' + (end - start) + ' ms.'); 7 | return response; 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /example/middleware/log/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['hello']); 4 | client.use(loghandler); 5 | client.hello("world", function(result) { 6 | console.log(result); 7 | }); 8 | -------------------------------------------------------------------------------- /example/middleware/log/loghandler.js: -------------------------------------------------------------------------------- 1 | /* 2 | module.exports = function(name, args, context, next) { 3 | console.log("before invoke:", name, args); 4 | var result = next(name, args, context); 5 | result.then(function(result) { 6 | console.log("after invoke:", name, args, result); 7 | }); 8 | return result; 9 | }; 10 | */ 11 | module.exports = function*(name, args, context, next) { 12 | console.log("before invoke:", name, args); 13 | var result = yield next(name, args, context); 14 | console.log("after invoke:", name, args, result); 15 | return result; 16 | }; 17 | -------------------------------------------------------------------------------- /example/middleware/log/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | function hello(name) { 4 | return "Hello " + name + "!"; 5 | } 6 | var server = hprose.Server.create("http://0.0.0.0:8080"); 7 | server.use(loghandler); 8 | server.add(hello); 9 | server.start(); 10 | -------------------------------------------------------------------------------- /example/middleware/log2/client.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | var client = hprose.Client.create("http://127.0.0.1:8080/", ['hello']); 4 | client.beforeFilter.use(loghandler); 5 | client.hello("world", function(result) { 6 | console.log(result); 7 | }); 8 | -------------------------------------------------------------------------------- /example/middleware/log2/loghandler.js: -------------------------------------------------------------------------------- 1 | var hprose = require('hprose'); 2 | module.exports = function*(request, context, next) { 3 | console.log(hprose.BytesIO.toString(request)); 4 | var response = yield next(request, context); 5 | console.log(hprose.BytesIO.toString(response)); 6 | return response; 7 | }; 8 | -------------------------------------------------------------------------------- /example/middleware/log2/server.js: -------------------------------------------------------------------------------- 1 | var hprose = require("hprose"); 2 | var loghandler = require("./loghandler.js"); 3 | function hello(name) { 4 | return "Hello " + name + "!"; 5 | } 6 | var server = hprose.Server.create("http://0.0.0.0:8080"); 7 | server.addFunction(hello); 8 | server.beforeFilter.use(loghandler); 9 | server.start(); 10 | -------------------------------------------------------------------------------- /example/proxyclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('hprose'); 5 | var client = hprose.Client.create('tcp://127.0.0.1:1234/', []); 6 | client.fullDuplex = true; 7 | client.maxPoolSize = 1; 8 | var proxy = client.useService(); 9 | 10 | proxy.hello("World", function(result) { 11 | console.log(result); 12 | }, function(name, error) { 13 | console.error(error); 14 | }); 15 | 16 | var weeks = { 17 | 'Monday': 'Mon', 18 | 'Tuesday': 'Tue', 19 | 'Wednesday': 'Wed', 20 | 'Thursday': 'Thu', 21 | 'Friday': 'Fri', 22 | 'Saturday': 'Sat', 23 | 'Sunday': 'Sun', 24 | }; 25 | 26 | proxy.swapKeyAndValue.onsuccess = function(result, args) { 27 | console.log(weeks.constructor, weeks); 28 | console.log(result.constructor, result); 29 | console.log(args.constructor, args); 30 | }; 31 | 32 | proxy.swapKeyAndValue.byref = true; 33 | 34 | proxy.swapKeyAndValue(weeks); -------------------------------------------------------------------------------- /example/proxyserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('hprose'); 5 | var client = hprose.Client.create('http://www.hprose.com/example/', []); 6 | function proxy(name, args) { 7 | return client.invoke(name, args, { mode: hprose.RawWithEndTag }); 8 | } 9 | var server = hprose.Server.create("tcp://0.0.0.0:1234"); 10 | server.addMissingFunction(proxy, { mode: hprose.RawWithEndTag }); 11 | process.on('SIGINT', function() { 12 | server.stop(); 13 | }); 14 | server.start(); 15 | -------------------------------------------------------------------------------- /example/serialize.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | "use strict"; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | console.log(hprose.unserialize(hprose.serialize(0))); 6 | console.log(hprose.unserialize(hprose.serialize(1))); 7 | console.log(hprose.unserialize(hprose.serialize(9))); 8 | console.log(hprose.unserialize(hprose.serialize(10))); 9 | console.log(hprose.unserialize(hprose.serialize(-1))); 10 | console.log(hprose.unserialize(hprose.serialize(100000))); 11 | console.log(hprose.unserialize(hprose.serialize(12345678909876))); 12 | console.log(hprose.unserialize(hprose.serialize(Math.PI))); 13 | console.log(hprose.unserialize(hprose.serialize(new Date()))); 14 | console.log(hprose.serialize("Hello World!").toString()); 15 | console.log(hprose.serialize("你好中国!🇨🇳").toString()); 16 | console.log(hprose.unserialize(hprose.serialize("Hello World!"))); 17 | console.log(hprose.unserialize(hprose.serialize("你好中国!🇨🇳"))); 18 | console.log(hprose.unserialize(hprose.serialize(new Buffer("你好"))).toString()); 19 | console.log(hprose.unserialize(new Buffer("l1234567890987654321234567890;"))); 20 | console.log(hprose.unserialize(hprose.serialize(NaN))); 21 | console.log(hprose.serialize(NaN).toString()); 22 | console.log(hprose.serialize(Infinity).toString()); 23 | console.log(hprose.serialize(-Infinity).toString()); 24 | console.log(hprose.serialize(true).toString()); 25 | console.log(hprose.serialize(false).toString()); 26 | console.log(hprose.serialize(undefined).toString()); 27 | console.log(hprose.serialize(null).toString()); 28 | console.log(hprose.serialize("").toString()); 29 | console.log(hprose.serialize(new Buffer(0)).toString()); 30 | console.log(hprose.serialize([3,3,4,5]).toString()); 31 | 32 | var s = hprose.serialize({"name": "MaBingyao", "alias": "MaBingyao", "age": 32, "sex": "male"}); 33 | console.log(s.toString()); 34 | console.log(hprose.unserialize(s)); 35 | function User(name, age) { 36 | this.name = name; 37 | this.age = age; 38 | } 39 | hprose.register(User, "MyUser"); 40 | var user1 = new User("张三", 32); 41 | var user2 = new User("李四", 28); 42 | s = hprose.serialize([user1, user2, user1, user2]); 43 | console.log(s.toString()); 44 | console.log(hprose.unserialize(s)); 45 | var arr = ["name", "sex", "sex"]; 46 | s = hprose.serialize(arr); 47 | console.log(s.toString()); 48 | console.log(hprose.unserialize(s)); 49 | 50 | // Test HarmonyMaps 51 | var map = new global.Map(); 52 | map.set(map, map); 53 | map.set(NaN, "NaN"); 54 | map.set(-0, "-0"); 55 | console.log(map.size); 56 | s = hprose.serialize(map); 57 | console.log(s.toString()); 58 | console.log(hprose.unserialize(s, false, true).size); 59 | -------------------------------------------------------------------------------- /example/server.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function hello(name, context) { 7 | context.clients.push("news", "this is a pushed message: " + name); 8 | context.clients.broadcast("news", {x: 1, y: 2, message: "this is a pushed object:" + name}); 9 | return 'Hello ' + name + '! -- ' + context.socket.remoteAddress; 10 | } 11 | 12 | async function hello2(name) { 13 | return await 'Hello ' + name + '!'; 14 | } 15 | 16 | function asyncHello(name, callback) { 17 | callback('Hello ' + name + '!'); 18 | } 19 | 20 | function getMaps() { 21 | var context = Array.prototype.pop.call(arguments); 22 | var result = {}; 23 | var key; 24 | for (key in arguments) { 25 | result[key] = arguments[key]; 26 | } 27 | return result; 28 | } 29 | 30 | function LogFilter() { 31 | this.inputFilter = function(value) { 32 | console.log(hprose.BytesIO.toString(value)); 33 | return value; 34 | }; 35 | this.outputFilter = function(value) { 36 | console.log(hprose.BytesIO.toString(value)); 37 | return value; 38 | }; 39 | } 40 | 41 | var server = hprose.Server.create("http://0.0.0.0:8080"); 42 | server.crossDomain = true; 43 | server.crossDomainXmlFile = './crossdomain.xml'; 44 | server.debug = true; 45 | server.filter = new LogFilter(); 46 | //server.simple = true; 47 | server.passContext = true; 48 | server.addFunctions([hello, hello2, getMaps]); 49 | server.addAsyncFunction(asyncHello); 50 | server.publish('news'); 51 | server.on('sendError', function(message) { 52 | console.log(message.stack); 53 | }); 54 | process.on('SIGINT', function() { 55 | server.stop(); 56 | }); 57 | server.start(); 58 | -------------------------------------------------------------------------------- /example/server2.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function LogFilter() { 7 | this.inputFilter = function(value) { 8 | console.log(hprose.BytesIO.toString(value)); 9 | return value; 10 | }; 11 | this.outputFilter = function(value) { 12 | console.log(hprose.BytesIO.toString(value)); 13 | return value; 14 | }; 15 | } 16 | 17 | function onBeforeInvoke(name) { 18 | var completer = new hprose.Completer(); 19 | if (name === "getUser") { 20 | completer.completeError(new Error(name)); 21 | } 22 | else { 23 | completer.complete(null); 24 | } 25 | return completer.future; 26 | } 27 | 28 | var server = hprose.Server.create("http://0.0.0.0:8080"); 29 | server.crossDomain = true; 30 | server.crossDomainXmlFile = './crossdomain.xml'; 31 | server.debug = true; 32 | server.onBeforeInvoke = onBeforeInvoke; 33 | server.add(function() {}, "getUser"); 34 | server.filter = new LogFilter(); 35 | //server.simple = true; 36 | server.on('sendError', function(e) { 37 | console.log(e.stack); 38 | }); 39 | process.on('SIGINT', function() { 40 | server.stop(); 41 | }); 42 | server.start(); 43 | -------------------------------------------------------------------------------- /example/tcpclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('tcp://127.0.0.1:4321/', []); 6 | client.fullDuplex = false; 7 | client.maxPoolSize = 2; 8 | client.simple = true; 9 | client.on('error', function(func, e) { 10 | console.log(func, e); 11 | }); 12 | var proxy = client.useService(['hello', 'hello2', 'getMaps']); 13 | var start = new Date().getTime(); 14 | var max = 100; 15 | var n = 0; 16 | client.subscribe('news', function(result) { 17 | console.log(result); 18 | }); 19 | var callback = function(result) { 20 | console.log(result); 21 | n++; 22 | if (n === max) { 23 | var end = new Date().getTime(); 24 | console.log(end - start); 25 | } 26 | }; 27 | for (var i = 0; i < max; i++) { 28 | proxy.hello(i, callback); 29 | } 30 | var end = new Date().getTime(); 31 | console.log(end - start); 32 | client.batch.begin(); 33 | proxy.getMaps('name', 'age', 'age', function(result) { 34 | console.log(result); 35 | }); 36 | proxy.getMaps('name', 'age', 'birthday', function(result) { 37 | console.log(hprose.BytesIO.toString(result)); 38 | console.log(hprose.unserialize(result)); 39 | console.log(hprose.serialize(hprose.unserialize(result)).toString()); 40 | }, hprose.Serialized); 41 | client.batch.end(); 42 | -------------------------------------------------------------------------------- /example/tcpclient2.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create(['tcp://127.0.0.1:4321/', 6 | 'tcp://127.0.0.1:1234/', 7 | 'tcp://127.0.0.1:1111/'], []); 8 | client.fullDuplex = true; 9 | client.maxPoolSize = 1; 10 | client.simple = true; 11 | client.on('error', function(func, e) { 12 | console.log(func, e); 13 | }); 14 | var proxy = client.useService(['hello', 'hello2', 'getMaps']); 15 | var start = new Date().getTime(); 16 | var max = 100; 17 | var n = 0; 18 | client.subscribe('news', function(result) { 19 | console.log(result); 20 | }); 21 | var callback = function(result) { 22 | console.log(result); 23 | n++; 24 | if (n === max) { 25 | var end = new Date().getTime(); 26 | console.log(end - start); 27 | } 28 | }; 29 | for (var i = 0; i < max; i++) { 30 | proxy.hello(i, callback); 31 | } 32 | var end = new Date().getTime(); 33 | console.log(end - start); 34 | client.batch.begin(); 35 | proxy.getMaps('name', 'age', 'age', function(result) { 36 | console.log(result); 37 | }); 38 | proxy.getMaps('name', 'age', 'birthday', function(result) { 39 | console.log(hprose.BytesIO.toString(result)); 40 | console.log(hprose.unserialize(result)); 41 | console.log(hprose.serialize(hprose.unserialize(result)).toString()); 42 | }, hprose.Serialized); 43 | client.batch.end(); 44 | -------------------------------------------------------------------------------- /example/tcpclient3.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('tcp://127.0.0.1:4321/', []); 6 | client.fullDuplex = false; 7 | //client.maxPoolSize = 1; 8 | client.simple = true; 9 | client.on('error', function(func, e) { 10 | console.log(func, e); 11 | }); 12 | var proxy = client.useService(['hello']); 13 | proxy.hello('world').delay(10000).then(function() { 14 | proxy.hello('world').then(function(result) { 15 | console.log(result); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /example/tcpclient4.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('tcp://127.0.0.1:4321/', ['hello']); 6 | client.fullDuplex = true; 7 | client.maxPoolSize = 1; 8 | var log = hprose.Future.wrap(console.log, console); 9 | log(client.hello("async world1")); 10 | log(client.hello("async world2")); 11 | log(client.hello("async world3")); 12 | log(client.hello("async world4")); 13 | log(client.hello("async world5")); 14 | log(client.hello("async world6")); 15 | 16 | // 串行异步 17 | client.hello("world1") 18 | .then(function(result) { 19 | console.log(result); 20 | return client.hello("world2"); 21 | }) 22 | .then(function(result) { 23 | console.log(result); 24 | return client.hello("world3"); 25 | }) 26 | .then(function(result) { 27 | console.log(result); 28 | return client.hello("world4"); 29 | }) 30 | .then(function(result) { 31 | console.log(result); 32 | return client.hello("world5"); 33 | }) 34 | .then(function(result) { 35 | console.log(result); 36 | return client.hello("world6"); 37 | }) 38 | .then(function(result) { 39 | console.log(result); 40 | client.close(); 41 | }); 42 | -------------------------------------------------------------------------------- /example/tcpserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function hello(name, context) { 7 | context.clients.push("news", "this is a pushed message: " + name); 8 | context.clients.broadcast("news", {x: 1, y: 2, message: "this is a pushed object:" + name}); 9 | return 'Hello ' + name + '! -- ' + context.socket.remoteAddress; 10 | } 11 | 12 | function hello2(name) { 13 | return name; 14 | } 15 | 16 | function asyncHello(name, callback) { 17 | callback('Hello ' + name + '!'); 18 | } 19 | 20 | function getMaps() { 21 | var context = Array.prototype.pop.call(arguments); 22 | var result = {}; 23 | var key; 24 | for (key in arguments) { 25 | result[key] = arguments[key]; 26 | } 27 | return result; 28 | } 29 | 30 | function LogFilter() { 31 | this.inputFilter = function(value) { 32 | try { 33 | console.log(hprose.BytesIO.toString(value)); 34 | } 35 | catch(e) { 36 | console.log(hprose.toBinaryString(value)); 37 | } 38 | return value; 39 | }; 40 | this.outputFilter = function(value) { 41 | try { 42 | console.log(hprose.BytesIO.toString(value)); 43 | } 44 | catch(e) { 45 | console.log(hprose.toBinaryString(value)); 46 | } 47 | return value; 48 | }; 49 | } 50 | 51 | var server = hprose.Server.create("tcp://0.0.0.0:4321"); 52 | server.debug = true; 53 | server.filter = new LogFilter(); 54 | server.simple = true; 55 | server.passContext = true; 56 | server.addFunctions([hello, hello2, getMaps]); 57 | server.addAsyncFunction(asyncHello); 58 | server.publish('news'); 59 | server.on('sendError', function(message) { 60 | console.log(message); 61 | }); 62 | process.on('SIGINT', function() { 63 | server.stop(); 64 | }); 65 | server.start(); 66 | -------------------------------------------------------------------------------- /example/testco.js: -------------------------------------------------------------------------------- 1 | var co = require('../lib/hprose.js').co; 2 | 3 | function* sleep() { 4 | return new Promise(function(resolve) { 5 | setTimeout(resolve, 1); 6 | }); 7 | }; 8 | 9 | co(function*() { 10 | 11 | for(var i = 0; true; ++i) { 12 | yield sleep(); 13 | 14 | if (i % 10000 === 0) { 15 | console.log(process.memoryUsage()); 16 | } 17 | 18 | } 19 | 20 | }).then(function() { 21 | console.log('finished') 22 | }, function(err) { 23 | console.log('caught error: ', err.stack); 24 | }); -------------------------------------------------------------------------------- /example/testthunkify.js: -------------------------------------------------------------------------------- 1 | var thunkify = require('../lib/hprose.js').thunkify; 2 | 3 | var delay = thunkify(function (time, callback) { 4 | setTimeout(callback, time); 5 | }); 6 | 7 | var result = delay(100); 8 | setTimeout(function () { 9 | console.log('a'); 10 | result(function () { 11 | console.log('c'); 12 | }); 13 | console.log('b'); 14 | }, 500); -------------------------------------------------------------------------------- /example/timeclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose'); 5 | var client = hprose.Client.create("http://127.0.0.1:8080"); 6 | var count = 0; 7 | client.subscribe('time', function(date) { 8 | if (++count > 10) { 9 | client.unsubscribe('time'); 10 | } 11 | else { 12 | console.log(date); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /example/timeoutclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('tcp://127.0.0.1:4321/', ['sum']); 6 | // client.fullDuplex = false; 7 | client.keepAlive = false; 8 | client.timeout = 600; 9 | 10 | client.sum(1, 2); 11 | client.sum(1, 2).then(function(result) { 12 | console.log("1 + 2 = " + result); 13 | }).catch(function() { 14 | client.sum(2, 3, function(result) { 15 | console.log("2 + 3 = " + result); 16 | }, { timeout: 20000 }); 17 | }) -------------------------------------------------------------------------------- /example/timeoutserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function sum(a, b) { 7 | var promise = new hprose.Future(); 8 | setTimeout(function() { 9 | promise.resolve(a + b); 10 | }, 1000); 11 | return promise; 12 | } 13 | 14 | var server = hprose.Server.create("tcp://0.0.0.0:4321"); 15 | server.addFunction(sum); 16 | process.on('SIGINT', function() { 17 | server.stop(); 18 | }); 19 | server.start(); 20 | -------------------------------------------------------------------------------- /example/timeserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose'); 5 | var server = hprose.Server.create("http://0.0.0.0:8080"); 6 | server.publish('time'); 7 | 8 | function ClientListFilter() { 9 | this.inputFilter = function(value) { 10 | return value; 11 | }; 12 | this.outputFilter = function(value, context) { 13 | console.log(context.clients.idlist('time')); 14 | return value; 15 | }; 16 | } 17 | 18 | server.filter = new ClientListFilter(); 19 | 20 | setInterval(function() { 21 | server.push('time', new Date()); 22 | }, 1000); 23 | 24 | process.on('SIGINT', function() { 25 | console.log("server is stoping!"); 26 | server.stop(); 27 | process.exit(); 28 | }); 29 | 30 | server.start(); 31 | -------------------------------------------------------------------------------- /example/unixclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('unix:/tmp/my.sock', []); 6 | 7 | //client.simple = true; 8 | client.on('error', function(func, e) { 9 | console.log(func, e); 10 | }); 11 | var proxy = client.useService(['hello', 'hello2', 'getMaps']); 12 | var start = new Date().getTime(); 13 | var max = 10; 14 | var n = 0; 15 | client.subscribe('news', function(result) { 16 | console.log(result); 17 | }); 18 | var callback = function(result) { 19 | console.log(result); 20 | n++; 21 | if (n === max) { 22 | var end = new Date().getTime(); 23 | console.log(end - start); 24 | } 25 | }; 26 | client.batch.begin(); 27 | for (var i = 0; i < max; i++) { 28 | proxy.hello(i, callback); 29 | } 30 | var end = new Date().getTime(); 31 | console.log(end - start); 32 | proxy.getMaps('name', 'age', 'age', function(result) { 33 | console.log(result); 34 | }); 35 | proxy.getMaps('name', 'age', 'birthday', function(result) { 36 | console.log(hprose.BytesIO.toString(result)); 37 | console.log(hprose.unserialize(result)); 38 | console.log(hprose.serialize(hprose.unserialize(result)).toString()); 39 | }, hprose.Serialized); 40 | client.batch.end(); 41 | -------------------------------------------------------------------------------- /example/unixserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function hello(name, context) { 7 | context.clients.push("news", "this is a pushed message: " + name); 8 | context.clients.broadcast("news", {x: 1, y: 2, message: "this is a pushed object:" + name}); 9 | return 'Hello ' + name + '!'; 10 | } 11 | 12 | function hello2(name) { 13 | return 'Hello ' + name + '!'; 14 | } 15 | 16 | function asyncHello(name, callback) { 17 | callback('Hello ' + name + '!'); 18 | } 19 | 20 | function getMaps() { 21 | var context = Array.prototype.pop.call(arguments); 22 | var result = {}; 23 | var key; 24 | for (key in arguments) { 25 | result[key] = arguments[key]; 26 | } 27 | return result; 28 | } 29 | 30 | function LogFilter() { 31 | this.inputFilter = function(value) { 32 | console.log(hprose.BytesIO.toString(value)); 33 | return value; 34 | }; 35 | this.outputFilter = function(value) { 36 | console.log(hprose.BytesIO.toString(value)); 37 | return value; 38 | }; 39 | } 40 | 41 | var server = hprose.Server.create("unix:/tmp/my.sock"); 42 | server.debug = true; 43 | server.filter = new LogFilter(); 44 | server.simple = true; 45 | server.passContext = true; 46 | server.addFunctions([hello, hello2, getMaps]); 47 | server.addAsyncFunction(asyncHello); 48 | server.publish('news'); 49 | server.on('sendError', function(message) { 50 | console.log(message); 51 | }); 52 | process.on('SIGINT', function() { 53 | server.stop(); 54 | }); 55 | server.start(); 56 | -------------------------------------------------------------------------------- /example/ws_client.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('ws://127.0.0.1:8080', []); 6 | client.keepAlive = false; 7 | client.simple = true; 8 | var var_dump = hprose.Future.wrap(console.log, console); 9 | var proxy = client.useService(['hello']); 10 | 11 | var_dump(proxy.hello('async world1')); 12 | var_dump(proxy.hello('async world2')); 13 | var_dump(proxy.hello('async world3')); 14 | var_dump(proxy.hello('async world4')); 15 | var_dump(proxy.hello('async world5')); 16 | var_dump(proxy.hello('async world6')); 17 | 18 | proxy.hello("world1") 19 | .then(function(result) { 20 | console.log(result); 21 | return proxy.hello("world2"); 22 | }) 23 | .then(function(result) { 24 | console.log(result); 25 | return proxy.hello("world3"); 26 | }) 27 | .then(function(result) { 28 | console.log(result); 29 | return proxy.hello("world4"); 30 | }) 31 | .then(function(result) { 32 | console.log(result); 33 | return proxy.hello("world5"); 34 | }) 35 | .then(function(result) { 36 | console.log(result); 37 | return proxy.hello("world6"); 38 | }) 39 | .then(function(result) { 40 | console.log(result); 41 | }); 42 | 43 | var_dump(proxy.hello('async world1')); 44 | var_dump(proxy.hello('async world2')); 45 | var_dump(proxy.hello('async world3')); 46 | var_dump(proxy.hello('async world4')); 47 | var_dump(proxy.hello('async world5')); 48 | var_dump(proxy.hello('async world6')); 49 | 50 | -------------------------------------------------------------------------------- /example/wsclient.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | var client = hprose.Client.create('ws://127.0.0.1:8080', []); 6 | client.keepAlive = false; 7 | client.simple = true; 8 | client.on('error', function(func, e) { 9 | console.log(func, e.stack); 10 | }); 11 | var proxy = client.useService(['hello', 'hello2', 'getMaps']); 12 | var start = new Date().getTime(); 13 | var max = 100; 14 | var n = 0; 15 | client.subscribe('news', function(result) { 16 | console.log(result); 17 | }); 18 | var callback = function(result) { 19 | console.log(result); 20 | n++; 21 | if (n === max) { 22 | var end = new Date().getTime(); 23 | console.log(end - start); 24 | } 25 | }; 26 | for (var i = 0; i < max; i++) { 27 | proxy.hello(i, callback); 28 | } 29 | var end = new Date().getTime(); 30 | console.log(end - start); 31 | client.batch.begin(); 32 | proxy.getMaps('name', 'age', 'age', function(result) { 33 | console.log(result); 34 | }); 35 | proxy.getMaps('name', 'age', 'birthday', function(result) { 36 | console.log(hprose.BytesIO.toString(result)); 37 | console.log(hprose.unserialize(result)); 38 | console.log(hprose.serialize(hprose.unserialize(result)).toString()); 39 | }, hprose.Serialized); 40 | client.batch.end(); 41 | -------------------------------------------------------------------------------- /example/wsserver.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true, eqeqeq:true */ 2 | 'use strict'; 3 | 4 | var hprose = require('../lib/hprose.js'); 5 | 6 | function hello(name, context) { 7 | context.clients.push("news", "this is a pushed message: " + name); 8 | context.clients.broadcast("news", {x: 1, y: 2, message: "this is a pushed object:" + name}); 9 | return 'Hello ' + name + '! -- ' + context.socket.remoteAddress; 10 | } 11 | 12 | function hello2(name) { 13 | return 'Hello ' + name + '!'; 14 | } 15 | 16 | function asyncHello(name, callback) { 17 | callback('Hello ' + name + '!'); 18 | } 19 | 20 | function getMaps() { 21 | var context = Array.prototype.pop.call(arguments); 22 | var result = {}; 23 | var key; 24 | for (key in arguments) { 25 | result[key] = arguments[key]; 26 | } 27 | return result; 28 | } 29 | 30 | function LogFilter() { 31 | this.inputFilter = function(value) { 32 | console.log(hprose.BytesIO.toString(value)); 33 | return value; 34 | }; 35 | this.outputFilter = function(value) { 36 | console.log(hprose.BytesIO.toString(value)); 37 | return value; 38 | }; 39 | } 40 | 41 | var server = hprose.Server.create("ws://0.0.0.0:8080"); 42 | server.debug = true; 43 | server.filter = new LogFilter(); 44 | server.simple = true; 45 | server.passContext = true; 46 | server.addFunctions([hello, hello2, getMaps]); 47 | server.addAsyncFunction(asyncHello); 48 | server.publish('news'); 49 | server.on('sendError', function(message) { 50 | console.log(message); 51 | }); 52 | server.start(); 53 | -------------------------------------------------------------------------------- /lib/client/HttpClient.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/client/HttpClient.js * 13 | * * 14 | * Hprose Http Client for Node.js. * 15 | * * 16 | * LastModified: Dec 4, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | var http = require('http'); 25 | var https = require('https'); 26 | var parse = require('url').parse; 27 | var TimeoutError = require('../common/TimeoutError'); 28 | 29 | var Client = global.hprose.Client; 30 | var BytesIO = global.hprose.BytesIO; 31 | var Future = global.hprose.Future; 32 | 33 | function noop(){} 34 | 35 | var s_cookieManager = {}; 36 | 37 | function setCookie(headers, host) { 38 | var name, values; 39 | function _setCookie(value) { 40 | var cookies, cookie, i; 41 | cookies = value.replace(/(^\s*)|(\s*$)/g, '').split(';'); 42 | cookie = {}; 43 | value = cookies[0].replace(/(^\s*)|(\s*$)/g, '').split('=', 2); 44 | if (value[1] === undefined) { value[1] = null; } 45 | cookie.name = value[0]; 46 | cookie.value = value[1]; 47 | for (i = 1; i < cookies.length; i++) { 48 | value = cookies[i].replace(/(^\s*)|(\s*$)/g, '').split('=', 2); 49 | if (value[1] === undefined) { value[1] = null; } 50 | cookie[value[0].toUpperCase()] = value[1]; 51 | } 52 | // Tomcat can return SetCookie2 with path wrapped in " 53 | if (cookie.PATH) { 54 | if (cookie.PATH.charAt(0) === '"') { 55 | cookie.PATH = cookie.PATH.substr(1); 56 | } 57 | if (cookie.PATH.charAt(cookie.PATH.length - 1) === '"') { 58 | cookie.PATH = cookie.PATH.substr(0, cookie.PATH.length - 1); 59 | } 60 | } 61 | else { 62 | cookie.PATH = '/'; 63 | } 64 | if (cookie.EXPIRES) { 65 | cookie.EXPIRES = Date.parse(cookie.EXPIRES); 66 | } 67 | if (cookie.DOMAIN) { 68 | cookie.DOMAIN = cookie.DOMAIN.toLowerCase(); 69 | } 70 | else { 71 | cookie.DOMAIN = host; 72 | } 73 | cookie.SECURE = (cookie.SECURE !== undefined); 74 | if (s_cookieManager[cookie.DOMAIN] === undefined) { 75 | s_cookieManager[cookie.DOMAIN] = {}; 76 | } 77 | s_cookieManager[cookie.DOMAIN][cookie.name] = cookie; 78 | } 79 | for (name in headers) { 80 | values = headers[name]; 81 | name = name.toLowerCase(); 82 | if ((name === 'set-cookie') || (name === 'set-cookie2')) { 83 | if (typeof(values) === 'string') { 84 | values = [values]; 85 | } 86 | values.forEach(_setCookie); 87 | } 88 | } 89 | } 90 | 91 | function getCookie(host, path, secure) { 92 | var cookies = []; 93 | for (var domain in s_cookieManager) { 94 | if (host.indexOf(domain) > -1) { 95 | var names = []; 96 | for (var name in s_cookieManager[domain]) { 97 | var cookie = s_cookieManager[domain][name]; 98 | if (cookie.EXPIRES && ((new Date()).getTime() > cookie.EXPIRES)) { 99 | names.push(name); 100 | } 101 | else if (path.indexOf(cookie.PATH) === 0) { 102 | if (((secure && cookie.SECURE) || 103 | !cookie.SECURE) && (cookie.value !== null)) { 104 | cookies.push(cookie.name + '=' + cookie.value); 105 | } 106 | } 107 | } 108 | for (var i in names) { 109 | delete s_cookieManager[domain][names[i]]; 110 | } 111 | } 112 | } 113 | if (cookies.length > 0) { 114 | return cookies.join('; '); 115 | } 116 | return ''; 117 | } 118 | 119 | function HttpClient(uri, functions, settings) { 120 | if (this.constructor !== HttpClient) { 121 | return new HttpClient(uri, functions, settings); 122 | } 123 | Client.call(this, uri, functions, settings); 124 | var _header = Object.create(null); 125 | 126 | var self = this; 127 | 128 | function getRequestHeader(headers) { 129 | var header = Object.create(null); 130 | var name, value; 131 | for (name in _header) { 132 | header[name] = _header[name]; 133 | } 134 | if (headers) { 135 | for (name in headers) { 136 | value = headers[name]; 137 | if (Array.isArray(value)) { 138 | header[name] = value.join(', '); 139 | } 140 | else { 141 | header[name] = value; 142 | } 143 | } 144 | } 145 | return header; 146 | } 147 | 148 | function send(request, future, context) { 149 | request = BytesIO.toBuffer(request); 150 | var options = parse(self.uri); 151 | var protocol = options.protocol; 152 | var client; 153 | var secure; 154 | if (protocol === 'http:') { 155 | client = http; 156 | secure = false; 157 | } 158 | else if (protocol === 'https:') { 159 | client = https; 160 | secure = true; 161 | } 162 | else { 163 | throw new Error('Unsupported ' + protocol + ' protocol!'); 164 | } 165 | options.keepAlive = self.keepAlive; 166 | for (var key in self.options) { 167 | options[key] = self.options[key]; 168 | } 169 | options.method = 'POST'; 170 | options.headers = getRequestHeader(context.httpHeader); 171 | options.headers['Content-Length'] = request.length; 172 | var cookie = getCookie(options.host, options.path, secure); 173 | if (cookie !== '') { 174 | options.headers.Cookie = cookie; 175 | } 176 | var req = client.request(options, function(resp) { 177 | context.httpHeader = resp.headers; 178 | var bytes = new BytesIO(); 179 | resp.on('data', function(data) { bytes.write(data); }); 180 | resp.on('end', function() { 181 | if (resp.statusCode === 200) { 182 | future.resolve(bytes.bytes); 183 | } 184 | else { 185 | future.reject(new Error(resp.statusCode + ':' + bytes.toString())); 186 | } 187 | }); 188 | resp.on('error', future.reject); 189 | if (resp.statusCode === 200) { 190 | setCookie(resp.headers, options.host); 191 | } 192 | }); 193 | req.on('error', future.reject); 194 | req.end(request); 195 | return req; 196 | } 197 | 198 | function sendAndReceive(request, context) { 199 | var future = new Future(); 200 | var req = send(request, future, context); 201 | if (context.timeout > 0) { 202 | future = future.timeout(context.timeout).catchError(function(e) { 203 | req.removeAllListeners('error'); 204 | req.on('error', noop); 205 | req.abort(); 206 | throw e; 207 | }, 208 | function(e) { 209 | return e instanceof TimeoutError; 210 | }); 211 | } 212 | if (context.oneway) { future.resolve(); } 213 | return future; 214 | } 215 | 216 | function setHeader(name, value) { 217 | if (name.toLowerCase() !== 'content-type' && 218 | name.toLowerCase() !== 'content-length' && 219 | name.toLowerCase() !== 'host') { 220 | if (value) { 221 | _header[name] = value; 222 | } 223 | else { 224 | delete _header[name]; 225 | } 226 | } 227 | } 228 | 229 | Object.defineProperties(this, { 230 | setHeader: { value: setHeader }, 231 | sendAndReceive: { value: sendAndReceive } 232 | }); 233 | } 234 | 235 | function checkuri(uri) { 236 | var protocol = parse(uri).protocol; 237 | if (protocol === 'http:' || 238 | protocol === 'https:') { 239 | return; 240 | } 241 | throw new Error('This client desn\'t support ' + protocol + ' scheme.'); 242 | } 243 | 244 | function create(uri, functions, settings) { 245 | if (typeof uri === 'string') { 246 | checkuri(uri); 247 | } 248 | else if (Array.isArray(uri)) { 249 | uri.forEach(function(uri) { checkuri(uri); }); 250 | } 251 | else { 252 | throw new Error('You should set server uri first!'); 253 | } 254 | return new HttpClient(uri, functions, settings); 255 | } 256 | 257 | Object.defineProperty(HttpClient, 'create', { value: create }); 258 | 259 | util.inherits(HttpClient, Client); 260 | 261 | global.hprose.HttpClient = HttpClient; 262 | -------------------------------------------------------------------------------- /lib/client/SocketClient.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/client/SocketClient.js * 13 | * * 14 | * Hprose Socket Client for Node.js. * 15 | * * 16 | * LastModified: Dec 2, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | var net = require('net'); 25 | var tls = require('tls'); 26 | var parse = require('url').parse; 27 | var TimeoutError = require('../common/TimeoutError'); 28 | 29 | var Client = global.hprose.Client; 30 | var BytesIO = global.hprose.BytesIO; 31 | var Future = global.hprose.Future; 32 | 33 | function setReceiveEvent(conn) { 34 | var bytes = new BytesIO(); 35 | var headerLength = 4; 36 | var dataLength = -1; 37 | var id = null; 38 | conn.on('data', function(chunk) { 39 | bytes.write(chunk); 40 | while (true) { 41 | if ((dataLength < 0) && (bytes.length >= headerLength)) { 42 | dataLength = bytes.readInt32BE(); 43 | if ((dataLength & 0x80000000) !== 0) { 44 | dataLength &= 0x7fffffff; 45 | headerLength = 8; 46 | } 47 | } 48 | if ((headerLength === 8) && (id === null) && (bytes.length >= headerLength)) { 49 | id = bytes.readInt32BE(); 50 | } 51 | if ((dataLength >= 0) && ((bytes.length - headerLength) >= dataLength)) { 52 | conn.emit('receive', bytes.read(dataLength), id); 53 | headerLength = 4; 54 | id = null; 55 | bytes.trunc(); 56 | dataLength = -1; 57 | } 58 | else { 59 | break; 60 | } 61 | } 62 | }); 63 | } 64 | 65 | function SocketTransporter(client) { 66 | if (client) { 67 | this.client = client; 68 | this.uri = this.client.uri; 69 | this.size = 0; 70 | this.pool = []; 71 | this.requests = []; 72 | } 73 | } 74 | 75 | Object.defineProperties(SocketTransporter.prototype, { 76 | create: { value: function() { 77 | var client = this.client; 78 | var parser = parse(this.uri); 79 | var protocol = parser.protocol; 80 | var socket; 81 | var options = {}; 82 | for (var key in client.options) { 83 | options[key] = client.options[key]; 84 | } 85 | if (protocol === 'tcp:' || 86 | protocol === 'tcp4:' || 87 | protocol === 'tcp6:') { 88 | socket = net; 89 | options.host = parser.hostname; 90 | options.port = parseInt(parser.port, 10); 91 | if (protocol === 'tcp4:') { 92 | options.family = 4; 93 | } 94 | else if (protocol === 'tcp6:') { 95 | options.family = 6; 96 | } 97 | } 98 | else if (protocol === 'tcps:' || 99 | protocol === 'tcp4s:' || 100 | protocol === 'tcp6s:' || 101 | protocol === 'tls:') { 102 | socket = tls; 103 | options.host = parser.hostname; 104 | options.port = parseInt(parser.port, 10); 105 | if (protocol === 'tcp4s:') { 106 | options.family = 4; 107 | } 108 | else if (protocol === 'tcp6s:') { 109 | options.family = 6; 110 | } 111 | } 112 | else if (protocol === 'unix:') { 113 | socket = net; 114 | options.path = parser.path; 115 | } 116 | else { 117 | throw new Error('Unsupported ' + protocol + ' protocol!'); 118 | } 119 | var conn = socket.connect(options); 120 | conn.setNoDelay(client.noDelay); 121 | conn.setKeepAlive(client.keepAlive); 122 | setReceiveEvent(conn); 123 | var self = this; 124 | conn.on('end', function() { conn.connected = false; }); 125 | conn.on('close', function() { conn.connected = false; --self.size; }); 126 | ++this.size; 127 | return conn; 128 | } } 129 | }); 130 | 131 | function FullDuplexSocketTransporter(client) { 132 | SocketTransporter.call(this, client); 133 | } 134 | 135 | FullDuplexSocketTransporter.prototype = Object.create( 136 | SocketTransporter.prototype, { 137 | fetch: { value: function() { 138 | var pool = this.pool; 139 | while (pool.length > 0) { 140 | var conn = pool.pop(); 141 | if (conn.connected) { 142 | if (conn.count === 0) { 143 | conn.removeAllListeners('timeout'); 144 | conn.ref(); 145 | } 146 | return conn; 147 | } 148 | } 149 | return null; 150 | } }, 151 | init: { value: function(conn) { 152 | var self = this; 153 | conn.count = 0; 154 | conn.futures = {}; 155 | conn.timeoutIds = {}; 156 | conn.on('receive', function (data, id) { 157 | var future = conn.futures[id]; 158 | if (future) { 159 | self.clean(conn, id); 160 | if (conn.count === 0) { 161 | self.recycle(conn); 162 | } 163 | future.resolve(data); 164 | } 165 | }); 166 | conn.on('error', function (e) { 167 | var futures = conn.futures; 168 | for (var id in futures) { 169 | var future = futures[id]; 170 | self.clean(conn, id); 171 | future.reject(e); 172 | } 173 | conn.destroy(); 174 | }); 175 | } }, 176 | recycle: { value: function(conn) { 177 | conn.unref(); 178 | conn.setTimeout(this.client.poolTimeout, function() { 179 | conn.connected = false; 180 | conn.end(); 181 | }); 182 | } }, 183 | clean: { value: function(conn, id) { 184 | if (conn.timeoutIds[id] !== undefined) { 185 | global.clearTimeout(conn.timeoutIds[id]); 186 | delete conn.timeoutIds[id]; 187 | } 188 | delete conn.futures[id]; 189 | --conn.count; 190 | this.sendNext(conn); 191 | } }, 192 | sendNext: { value: function(conn) { 193 | if (conn.count < 10) { 194 | if (this.requests.length > 0) { 195 | var request = this.requests.pop(); 196 | request.push(conn); 197 | this.send.apply(this, request); 198 | } 199 | else { 200 | if (this.pool.lastIndexOf(conn) < 0) { 201 | this.pool.push(conn); 202 | } 203 | } 204 | } 205 | } }, 206 | send: { value: function(request, future, id, context, conn) { 207 | var self = this; 208 | 209 | var timeout = context.timeout; 210 | if (timeout > 0) { 211 | conn.timeoutIds[id] = global.setTimeout(function() { 212 | self.clean(conn, id); 213 | if (conn.count === 0) { 214 | self.recycle(conn); 215 | } 216 | future.reject(new TimeoutError('timeout')); 217 | }, timeout); 218 | } 219 | conn.count++; 220 | conn.futures[id] = future; 221 | 222 | var len = request.length; 223 | var buf = new Buffer(8 + len); 224 | buf.writeInt32BE(len | 0x80000000, 0); 225 | buf.writeInt32BE(id, 4); 226 | for (var i = 0; i < len; i++) { 227 | buf[i + 8] = request[i]; 228 | } 229 | conn.write(buf, function() { 230 | self.sendNext(conn); 231 | }); 232 | } }, 233 | getNextId: { value: function() { 234 | return (this.nextid < 0x7fffffff) ? ++this.nextid : this.nextid = 0; 235 | } }, 236 | sendAndReceive: { value: function(request, future, context) { 237 | var conn = this.fetch(); 238 | var id = this.getNextId(); 239 | if (conn) { 240 | this.send(request, future, id, context, conn); 241 | } 242 | else if (this.size < this.client.maxPoolSize) { 243 | conn = this.create(); 244 | conn.on('error', function(e) { 245 | conn.destroy(); 246 | future.reject(e); 247 | }); 248 | var self = this; 249 | conn.once('connect', function() { 250 | conn.removeAllListeners('error'); 251 | conn.connected = true; 252 | self.init(conn); 253 | self.send(request, future, id, context, conn); 254 | }); 255 | } 256 | else { 257 | this.requests.push([request, future, id, context]); 258 | } 259 | } } 260 | }); 261 | 262 | FullDuplexSocketTransporter.prototype.constructor = SocketTransporter; 263 | 264 | function HalfDuplexSocketTransporter(client) { 265 | SocketTransporter.call(this, client); 266 | } 267 | 268 | HalfDuplexSocketTransporter.prototype = Object.create( 269 | SocketTransporter.prototype, { 270 | fetch: { value: function() { 271 | var pool = this.pool; 272 | while (pool.length > 0) { 273 | var conn = pool.pop(); 274 | if (conn.connected) { 275 | conn.removeAllListeners('timeout'); 276 | conn.ref(); 277 | return conn; 278 | } 279 | } 280 | return null; 281 | } }, 282 | recycle: { value: function(conn) { 283 | if (this.pool.lastIndexOf(conn) < 0) { 284 | conn.unref(); 285 | conn.setTimeout(this.client.poolTimeout, function() { 286 | conn.connected = false; 287 | conn.end(); 288 | }); 289 | this.pool.push(conn); 290 | } 291 | } }, 292 | clean: { value: function(conn) { 293 | conn.removeAllListeners('receive'); 294 | conn.removeAllListeners('error'); 295 | if (conn.timeoutId !== undefined) { 296 | global.clearTimeout(conn.timeoutId); 297 | delete conn.timeoutId; 298 | } 299 | } }, 300 | sendNext: { value: function(conn) { 301 | if (this.requests.length > 0) { 302 | var request = this.requests.pop(); 303 | request.push(conn); 304 | this.send.apply(this, request); 305 | } 306 | else { 307 | this.recycle(conn); 308 | } 309 | } }, 310 | send: { value: function(request, future, context, conn) { 311 | var self = this; 312 | var timeout = context.timeout; 313 | if (timeout > 0) { 314 | conn.timeoutId = global.setTimeout(function() { 315 | self.clean(conn); 316 | conn.connected = false; 317 | conn.end(); 318 | future.reject(new TimeoutError('timeout')); 319 | }, timeout); 320 | } 321 | conn.on('receive', function(data) { 322 | self.clean(conn); 323 | self.sendNext(conn); 324 | future.resolve(data); 325 | }); 326 | conn.on('error', function(e) { 327 | self.clean(conn); 328 | conn.destroy(); 329 | future.reject(e); 330 | }); 331 | 332 | var len = request.length; 333 | var buf = new Buffer(4 + len); 334 | buf.writeInt32BE(len, 0); 335 | for (var i = 0; i < len; i++) { 336 | buf[i + 4] = request[i]; 337 | } 338 | conn.write(buf); 339 | } }, 340 | sendAndReceive: { value: function(request, future, context) { 341 | var conn = this.fetch(); 342 | if (conn) { 343 | this.send(request, future, context, conn); 344 | } 345 | else if (this.size < this.client.maxPoolSize) { 346 | conn = this.create(); 347 | var self = this; 348 | conn.on('error', function(e) { 349 | conn.destroy(); 350 | future.reject(e); 351 | }); 352 | conn.once('connect', function() { 353 | conn.removeAllListeners('error'); 354 | conn.connected = true; 355 | self.send(request, future, context, conn); 356 | }); 357 | } 358 | else { 359 | this.requests.push([request, future, context]); 360 | } 361 | } } 362 | }); 363 | 364 | HalfDuplexSocketTransporter.prototype.constructor = SocketTransporter; 365 | 366 | function SocketClient(uri, functions, settings) { 367 | if (this.constructor !== SocketClient) { 368 | return new SocketClient(uri, functions, settings); 369 | } 370 | Client.call(this, uri, functions, settings); 371 | 372 | var self = this; 373 | var _noDelay = true; 374 | var _fullDuplex = false; 375 | var _maxPoolSize = 10; 376 | var _poolTimeout = 30000; 377 | var fdtrans = null; 378 | var hdtrans = null; 379 | 380 | function getNoDelay() { 381 | return _noDelay; 382 | } 383 | 384 | function setNoDelay(value) { 385 | _noDelay = !!value; 386 | } 387 | 388 | function getFullDuplex() { 389 | return _fullDuplex; 390 | } 391 | 392 | function setFullDuplex(value) { 393 | _fullDuplex = !!value; 394 | } 395 | 396 | function getMaxPoolSize() { 397 | return _maxPoolSize; 398 | } 399 | 400 | function setMaxPoolSize(value) { 401 | if (typeof(value) === 'number') { 402 | _maxPoolSize = value | 0; 403 | if (_maxPoolSize < 1) { 404 | _maxPoolSize = 10; 405 | } 406 | } 407 | else { 408 | _maxPoolSize = 10; 409 | } 410 | } 411 | 412 | function getPoolTimeout() { 413 | return _poolTimeout; 414 | } 415 | 416 | function setPoolTimeout(value) { 417 | if (typeof(value) === 'number') { 418 | _poolTimeout = value | 0; 419 | } 420 | else { 421 | _poolTimeout = 0; 422 | } 423 | } 424 | 425 | function sendAndReceive(request, context) { 426 | var future = new Future(); 427 | if (_fullDuplex) { 428 | if ((fdtrans === null) || (fdtrans.uri !== self.uri)) { 429 | fdtrans = new FullDuplexSocketTransporter(self); 430 | } 431 | fdtrans.sendAndReceive(request, future, context); 432 | } 433 | else { 434 | if ((hdtrans === null) || (hdtrans.uri !== self.uri)) { 435 | hdtrans = new HalfDuplexSocketTransporter(self); 436 | } 437 | hdtrans.sendAndReceive(request, future, context); 438 | } 439 | if (context.oneway) { future.resolve(); } 440 | return future; 441 | } 442 | 443 | Object.defineProperties(this, { 444 | noDelay: { get: getNoDelay, set: setNoDelay }, 445 | fullDuplex: { get: getFullDuplex, set: setFullDuplex }, 446 | maxPoolSize: { get: getMaxPoolSize, set: setMaxPoolSize }, 447 | poolTimeout: { get: getPoolTimeout, set: setPoolTimeout }, 448 | sendAndReceive: { value: sendAndReceive } 449 | }); 450 | } 451 | 452 | function checkuri(uri) { 453 | var protocol = parse(uri).protocol; 454 | if (protocol === 'tcp:' || 455 | protocol === 'tcp4:'|| 456 | protocol === 'tcp6:' || 457 | protocol === 'tcps:' || 458 | protocol === 'tcp4s:' || 459 | protocol === 'tcp6s:' || 460 | protocol === 'tls:' || 461 | protocol === 'unix:') { 462 | return; 463 | } 464 | throw new Error('This client desn\'t support ' + protocol + ' scheme.'); 465 | } 466 | 467 | function create(uri, functions, settings) { 468 | if (typeof uri === 'string') { 469 | checkuri(uri); 470 | } 471 | else if (Array.isArray(uri)) { 472 | uri.forEach(function(uri) { checkuri(uri); }); 473 | } 474 | else { 475 | throw new Error('You should set server uri first!'); 476 | } 477 | return new SocketClient(uri, functions, settings); 478 | } 479 | 480 | Object.defineProperty(SocketClient, 'create', { value: create }); 481 | 482 | util.inherits(SocketClient, Client); 483 | 484 | global.hprose.SocketClient = SocketClient; 485 | global.hprose.TcpClient = SocketClient; 486 | global.hprose.UnixClient = SocketClient; 487 | -------------------------------------------------------------------------------- /lib/client/WebSocketClient.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | /**********************************************************\ 10 | * * 11 | * hprose/client/WebSocketClient.js * 12 | * * 13 | * Hprose WebSocket Client for HTML5. * 14 | * * 15 | * LastModified: Aug 20, 2017 * 16 | * Author: Ma Bingyao * 17 | * * 18 | \**********************************************************/ 19 | 20 | 'use strict'; 21 | 22 | var util = require('util'); 23 | var parse = require('url').parse; 24 | 25 | /*jshint -W079*/ 26 | var WebSocket = require('ws'); 27 | 28 | var Client = global.hprose.Client; 29 | var BytesIO = global.hprose.BytesIO; 30 | var Future = global.hprose.Future; 31 | var TimeoutError = require('../common/TimeoutError'); 32 | 33 | function WebSocketClient(uri, functions, settings) { 34 | if (this.constructor !== WebSocketClient) { 35 | return new WebSocketClient(uri, functions, settings); 36 | } 37 | Client.call(this, uri, functions, settings); 38 | 39 | var _id = 0; 40 | var _count = 0; 41 | var _futures = []; 42 | var _requests = []; 43 | var _ready = null; 44 | var ws = null; 45 | 46 | var self = this; 47 | 48 | function getNextId() { 49 | return (_id < 0x7fffffff) ? ++_id : _id = 0; 50 | } 51 | 52 | function send(id, request) { 53 | var bytes = new BytesIO(); 54 | bytes.writeInt32BE(id); 55 | if (request.constructor === String) { 56 | bytes.writeString(request); 57 | } 58 | else { 59 | bytes.write(request); 60 | } 61 | var future = _futures[id]; 62 | try { 63 | ws.send(bytes.bytes); 64 | } 65 | catch (e) { 66 | future.reject(e); 67 | } 68 | } 69 | function onopen() { 70 | _ready.resolve(); 71 | } 72 | function onmessage(data) { 73 | var bytes = new BytesIO(data); 74 | var id = bytes.readInt32BE(); 75 | var future = _futures[id]; 76 | delete _futures[id]; 77 | if (future !== undefined) { 78 | --_count; 79 | future.resolve(bytes.read(bytes.length - 4)); 80 | } 81 | if ((_count < 100) && (_requests.length > 0)) { 82 | ++_count; 83 | var request = _requests.pop(); 84 | _ready.then(function() { send(request[0], request[1]); }); 85 | } 86 | if (_count === 0) { 87 | if (!self.keepAlive) { close(); } 88 | } 89 | } 90 | function onclose(code, message) { 91 | onerror(new Error(code + ':' + message)); 92 | ws = null; 93 | } 94 | function onerror(error) { 95 | _futures.forEach(function(future, id) { 96 | future.reject(error); 97 | delete _futures[id]; 98 | }); 99 | _count = 0; 100 | } 101 | function connect() { 102 | _ready = new Future(); 103 | self.setOption('perMessageDeflate', false); 104 | ws = new WebSocket(self.uri, self.options); 105 | ws.on('open', onopen); 106 | ws.on('message', onmessage); 107 | ws.on('error', onerror); 108 | ws.on('close', onclose); 109 | } 110 | function sendAndReceive(request, context) { 111 | var id = getNextId(); 112 | var future = new Future(); 113 | _futures[id] = future; 114 | if (context.timeout > 0) { 115 | future = future.timeout(context.timeout).catchError(function(e) { 116 | delete _futures[id]; 117 | --_count; 118 | close(); 119 | throw e; 120 | }, 121 | function(e) { 122 | return e instanceof TimeoutError; 123 | }); 124 | } 125 | if (ws === null || 126 | ws.readyState === WebSocket.CLOSING || 127 | ws.readyState === WebSocket.CLOSED) { 128 | connect(); 129 | } 130 | if (_count < 100) { 131 | ++_count; 132 | _ready.then(function() { send(id, request); }); 133 | } 134 | else { 135 | _requests.push([id, request]); 136 | } 137 | if (context.oneway) { future.resolve(); } 138 | return future; 139 | } 140 | function close() { 141 | if (ws !== null) { 142 | ws.removeAllListeners('open'); 143 | ws.removeAllListeners('message'); 144 | ws.removeAllListeners('error'); 145 | ws.removeAllListeners('close'); 146 | ws.close(); 147 | } 148 | } 149 | Object.defineProperties(this, { 150 | sendAndReceive: { value: sendAndReceive }, 151 | close: { value: close } 152 | }); 153 | } 154 | 155 | function checkuri(uri) { 156 | var protocol = parse(uri).protocol; 157 | if (protocol === 'ws:' || 158 | protocol === 'wss:') { 159 | return; 160 | } 161 | throw new Error('This client desn\'t support ' + protocol + ' scheme.'); 162 | } 163 | 164 | function create(uri, functions, settings) { 165 | if (typeof uri === 'string') { 166 | checkuri(uri); 167 | } 168 | else if (Array.isArray(uri)) { 169 | uri.forEach(function(uri) { checkuri(uri); }); 170 | } 171 | else { 172 | throw new Error('You should set server uri first!'); 173 | } 174 | return new WebSocketClient(uri, functions, settings); 175 | } 176 | 177 | Object.defineProperty(WebSocketClient, 'create', { value: create }); 178 | 179 | util.inherits(WebSocketClient, Client); 180 | 181 | global.hprose.WebSocketClient = WebSocketClient; 182 | -------------------------------------------------------------------------------- /lib/common/HarmonyMaps.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/common/HarmonyMaps.js * 13 | * * 14 | * Harmony Maps for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | (function() { 22 | 'use strict'; 23 | 24 | var hasWeakMap = 'WeakMap' in global; 25 | var hasMap = 'Map' in global; 26 | var hasForEach = true; 27 | 28 | if (hasMap) { 29 | hasForEach = 'forEach' in new global.Map(); 30 | } 31 | 32 | if (hasWeakMap && hasMap && hasForEach) { return; } 33 | 34 | var namespaces = Object.create(null); 35 | var count = 0; 36 | var reDefineValueOf = function (obj) { 37 | var privates = Object.create(null); 38 | var baseValueOf = obj.valueOf; 39 | Object.defineProperty(obj, 'valueOf', { 40 | value: function (namespace, n) { 41 | if ((this === obj) && 42 | (n in namespaces) && 43 | (namespaces[n] === namespace)) { 44 | if (!(n in privates)) { 45 | privates[n] = Object.create(null); 46 | } 47 | return privates[n]; 48 | } 49 | else { 50 | return baseValueOf.apply(this, arguments); 51 | } 52 | }, 53 | writable: true, 54 | configurable: true, 55 | enumerable: false 56 | }); 57 | }; 58 | 59 | if (!hasWeakMap) { 60 | global.WeakMap = function WeakMap() { 61 | var namespace = Object.create(null); 62 | var n = count++; 63 | namespaces[n] = namespace; 64 | var map = function (key) { 65 | if (key !== Object(key)) { 66 | throw new Error('value is not a non-null object'); 67 | } 68 | var privates = key.valueOf(namespace, n); 69 | if (privates !== key.valueOf()) { 70 | return privates; 71 | } 72 | reDefineValueOf(key); 73 | return key.valueOf(namespace, n); 74 | }; 75 | var m = Object.create(WeakMap.prototype, { 76 | get: { 77 | value: function (key) { 78 | return map(key).value; 79 | } 80 | }, 81 | set: { 82 | value: function (key, value) { 83 | map(key).value = value; 84 | } 85 | }, 86 | has: { 87 | value: function (key) { 88 | return 'value' in map(key); 89 | } 90 | }, 91 | 'delete': { 92 | value: function (key) { 93 | return delete map(key).value; 94 | } 95 | }, 96 | clear: { 97 | value: function () { 98 | delete namespaces[n]; 99 | n = count++; 100 | namespaces[n] = namespace; 101 | } 102 | } 103 | }); 104 | if (arguments.length > 0 && Array.isArray(arguments[0])) { 105 | var iterable = arguments[0]; 106 | for (var i = 0, len = iterable.length; i < len; i++) { 107 | m.set(iterable[i][0], iterable[i][1]); 108 | } 109 | } 110 | return m; 111 | }; 112 | } 113 | 114 | if (!hasMap) { 115 | var objectMap = function () { 116 | var namespace = Object.create(null); 117 | var n = count++; 118 | var nullMap = Object.create(null); 119 | namespaces[n] = namespace; 120 | var map = function (key) { 121 | if (key === null) { return nullMap; } 122 | var privates = key.valueOf(namespace, n); 123 | if (privates !== key.valueOf()) { return privates; } 124 | reDefineValueOf(key); 125 | return key.valueOf(namespace, n); 126 | }; 127 | return { 128 | get: function (key) { return map(key).value; }, 129 | set: function (key, value) { map(key).value = value; }, 130 | has: function (key) { return 'value' in map(key); }, 131 | 'delete': function (key) { return delete map(key).value; }, 132 | clear: function () { 133 | delete namespaces[n]; 134 | n = count++; 135 | namespaces[n] = namespace; 136 | } 137 | }; 138 | }; 139 | var noKeyMap = function () { 140 | var map = Object.create(null); 141 | return { 142 | get: function () { return map.value; }, 143 | set: function (_, value) { map.value = value; }, 144 | has: function () { return 'value' in map; }, 145 | 'delete': function () { return delete map.value; }, 146 | clear: function () { map = Object.create(null); } 147 | }; 148 | }; 149 | var scalarMap = function () { 150 | var map = Object.create(null); 151 | return { 152 | get: function (key) { return map[key]; }, 153 | set: function (key, value) { map[key] = value; }, 154 | has: function (key) { return key in map; }, 155 | 'delete': function (key) { return delete map[key]; }, 156 | clear: function () { map = Object.create(null); } 157 | }; 158 | }; 159 | global.Map = function Map() { 160 | var map = { 161 | 'number': scalarMap(), 162 | 'string': scalarMap(), 163 | 'boolean': scalarMap(), 164 | 'object': objectMap(), 165 | 'function': objectMap(), 166 | 'unknown': objectMap(), 167 | 'undefined': noKeyMap(), 168 | 'null': noKeyMap() 169 | }; 170 | var size = 0; 171 | var keys = []; 172 | var m = Object.create(Map.prototype, { 173 | size: { 174 | get : function () { return size; } 175 | }, 176 | get: { 177 | value: function (key) { 178 | return map[typeof(key)].get(key); 179 | } 180 | }, 181 | set: { 182 | value: function (key, value) { 183 | if (!this.has(key)) { 184 | keys.push(key); 185 | size++; 186 | } 187 | map[typeof(key)].set(key, value); 188 | } 189 | }, 190 | has: { 191 | value: function (key) { 192 | return map[typeof(key)].has(key); 193 | } 194 | }, 195 | 'delete': { 196 | value: function (key) { 197 | if (this.has(key)) { 198 | size--; 199 | keys.splice(keys.indexOf(key), 1); 200 | return map[typeof(key)]['delete'](key); 201 | } 202 | return false; 203 | } 204 | }, 205 | clear: { 206 | value: function () { 207 | keys.length = 0; 208 | for (var key in map) { map[key].clear(); } 209 | size = 0; 210 | } 211 | }, 212 | forEach: { 213 | value: function (callback, thisArg) { 214 | for (var i = 0, n = keys.length; i < n; i++) { 215 | callback.call(thisArg, this.get(keys[i]), keys[i], this); 216 | } 217 | } 218 | } 219 | }); 220 | if (arguments.length > 0 && Array.isArray(arguments[0])) { 221 | var iterable = arguments[0]; 222 | for (var i = 0, len = iterable.length; i < len; i++) { 223 | m.set(iterable[i][0], iterable[i][1]); 224 | } 225 | } 226 | return m; 227 | }; 228 | } 229 | 230 | if (!hasForEach) { 231 | var OldMap = global.Map; 232 | global.Map = function Map() { 233 | var map = new OldMap(); 234 | var size = 0; 235 | var keys = []; 236 | var m = Object.create(Map.prototype, { 237 | size: { 238 | get : function () { return size; } 239 | }, 240 | get: { 241 | value: function (key) { 242 | return map.get(key); 243 | } 244 | }, 245 | set: { 246 | value: function (key, value) { 247 | if (!map.has(key)) { 248 | keys.push(key); 249 | size++; 250 | } 251 | map.set(key, value); 252 | } 253 | }, 254 | has: { 255 | value: function (key) { 256 | return map.has(key); 257 | } 258 | }, 259 | 'delete': { 260 | value: function (key) { 261 | if (map.has(key)) { 262 | size--; 263 | keys.splice(keys.indexOf(key), 1); 264 | return map['delete'](key); 265 | } 266 | return false; 267 | } 268 | }, 269 | clear: { 270 | value: function () { 271 | if ('clear' in map) { 272 | map.clear(); 273 | } 274 | else { 275 | for (var i = 0, n = keys.length; i < n; i++) { 276 | map['delete'](keys[i]); 277 | } 278 | } 279 | keys.length = 0; 280 | size = 0; 281 | } 282 | }, 283 | forEach: { 284 | value: function (callback, thisArg) { 285 | for (var i = 0, n = keys.length; i < n; i++) { 286 | callback.call(thisArg, this.get(keys[i]), keys[i], this); 287 | } 288 | } 289 | } 290 | }); 291 | if (arguments.length > 0 && Array.isArray(arguments[0])) { 292 | var iterable = arguments[0]; 293 | for (var i = 0, len = iterable.length; i < len; i++) { 294 | m.set(iterable[i][0], iterable[i][1]); 295 | } 296 | } 297 | return m; 298 | }; 299 | } 300 | })(); 301 | -------------------------------------------------------------------------------- /lib/common/Helper.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/common/Helper.js * 13 | * * 14 | * Hprose Helper for Node.js. * 15 | * * 16 | * LastModified: Oct 12, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | (function() { 22 | 'use strict'; 23 | 24 | function generic(method) { 25 | if (typeof method !== "function") { 26 | throw new TypeError(method + " is not a function"); 27 | } 28 | return function(context) { 29 | return method.apply(context, Array.prototype.slice.call(arguments, 1)); 30 | }; 31 | } 32 | 33 | var arrayLikeObjectArgumentsEnabled = true; 34 | 35 | try { 36 | String.fromCharCode.apply(String, new Uint8Array([1])); 37 | } 38 | catch (e) { 39 | arrayLikeObjectArgumentsEnabled = false; 40 | } 41 | 42 | function toArray(arrayLikeObject) { 43 | var n = arrayLikeObject.length; 44 | var a = new Array(n); 45 | for (var i = 0; i < n; ++i) { 46 | a[i] = arrayLikeObject[i]; 47 | } 48 | return a; 49 | } 50 | 51 | var getCharCodes = arrayLikeObjectArgumentsEnabled ? function(bytes) { return bytes; } : toArray; 52 | 53 | function toBinaryString(bytes) { 54 | if (bytes instanceof ArrayBuffer) { 55 | bytes = new Uint8Array(bytes); 56 | } 57 | var n = bytes.length; 58 | if (n < 0xFFFF) { 59 | return String.fromCharCode.apply(String, getCharCodes(bytes)); 60 | } 61 | var remain = n & 0x7FFF; 62 | var count = n >> 15; 63 | var a = new Array(remain ? count + 1 : count); 64 | for (var i = 0; i < count; ++i) { 65 | a[i] = String.fromCharCode.apply(String, getCharCodes(bytes.subarray(i << 15, (i + 1) << 15))); 66 | } 67 | if (remain) { 68 | a[count] = String.fromCharCode.apply(String, getCharCodes(bytes.subarray(count << 15, n))); 69 | } 70 | return a.join(''); 71 | } 72 | 73 | function toUint8Array(bs) { 74 | var n = bs.length; 75 | var data = new Uint8Array(n); 76 | for (var i = 0; i < n; i++) { 77 | data[i] = bs.charCodeAt(i) & 0xFF; 78 | } 79 | return data; 80 | } 81 | 82 | var isObjectEmpty = function (obj) { 83 | if (obj) { 84 | var prop; 85 | for (prop in obj) { 86 | return false; 87 | } 88 | } 89 | return true; 90 | } 91 | 92 | global.hprose.generic = generic; 93 | global.hprose.toBinaryString = toBinaryString; 94 | global.hprose.toUint8Array = toUint8Array; 95 | global.hprose.toArray = toArray; 96 | global.hprose.isObjectEmpty = isObjectEmpty; 97 | 98 | })(); 99 | -------------------------------------------------------------------------------- /lib/common/Polyfill.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * Polyfill.js * 13 | * * 14 | * Polyfill for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | /* Function */ 23 | if (!Function.prototype.bind) { 24 | Object.defineProperty(Function.prototype, 'bind', { value: function(oThis) { 25 | if (typeof this !== 'function') { 26 | throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 27 | } 28 | var aArgs = Array.prototype.slice.call(arguments, 1), 29 | toBind = this, 30 | NOP = function() {}, 31 | bound = function() { 32 | return toBind.apply(this instanceof NOP ? this : oThis, 33 | aArgs.concat(Array.prototype.slice.call(arguments))); 34 | }; 35 | if (this.prototype) { 36 | NOP.prototype = this.prototype; 37 | } 38 | bound.prototype = new NOP(); 39 | return bound; 40 | } }); 41 | } 42 | /* Array */ 43 | if (!Array.prototype.includes) { 44 | Object.defineProperty(Array.prototype, 'includes', { value: function(searchElement /*, fromIndex*/ ) { 45 | var O = Object(this); 46 | var len = parseInt(O.length, 10) || 0; 47 | if (len === 0) { 48 | return false; 49 | } 50 | var n = parseInt(arguments[1], 10) || 0; 51 | var k; 52 | if (n >= 0) { 53 | k = n; 54 | } 55 | else { 56 | k = len + n; 57 | if (k < 0) { k = 0; } 58 | } 59 | var currentElement; 60 | while (k < len) { 61 | currentElement = O[k]; 62 | if (searchElement === currentElement || 63 | (searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN 64 | return true; 65 | } 66 | k++; 67 | } 68 | return false; 69 | } }); 70 | } 71 | if (!Array.prototype.find) { 72 | Object.defineProperty(Array.prototype, 'find', { value: function(predicate) { 73 | if (this === null || this === undefined) { 74 | throw new TypeError('Array.prototype.find called on null or undefined'); 75 | } 76 | if (typeof predicate !== 'function') { 77 | throw new TypeError('predicate must be a function'); 78 | } 79 | var list = Object(this); 80 | var length = list.length >>> 0; 81 | var thisArg = arguments[1]; 82 | var value; 83 | for (var i = 0; i < length; i++) { 84 | value = list[i]; 85 | if (predicate.call(thisArg, value, i, list)) { 86 | return value; 87 | } 88 | } 89 | return undefined; 90 | } }); 91 | } 92 | if (!Array.prototype.findIndex) { 93 | Object.defineProperty(Array.prototype, 'findIndex', { value: function(predicate) { 94 | if (this === null || this === undefined) { 95 | throw new TypeError('Array.prototype.findIndex called on null or undefined'); 96 | } 97 | if (typeof predicate !== 'function') { 98 | throw new TypeError('predicate must be a function'); 99 | } 100 | var list = Object(this); 101 | var length = list.length >>> 0; 102 | var thisArg = arguments[1]; 103 | var value; 104 | 105 | for (var i = 0; i < length; i++) { 106 | value = list[i]; 107 | if (predicate.call(thisArg, value, i, list)) { 108 | return i; 109 | } 110 | } 111 | return -1; 112 | } }); 113 | } 114 | if (!Array.prototype.fill) { 115 | Object.defineProperty(Array.prototype, 'fill', { value: function(value) { 116 | if (this === null || this === undefined) { 117 | throw new TypeError('this is null or not defined'); 118 | } 119 | var O = Object(this); 120 | var len = O.length >>> 0; 121 | var start = arguments[1]; 122 | var relativeStart = start >> 0; 123 | var k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len); 124 | var end = arguments[2]; 125 | var relativeEnd = end === undefined ? len : end >> 0; 126 | var f = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len); 127 | 128 | while (k < f) { 129 | O[k] = value; 130 | k++; 131 | } 132 | return O; 133 | } }); 134 | } 135 | if (!Array.prototype.copyWithin) { 136 | Object.defineProperty(Array.prototype, 'copyWithin', { value: function(target, start/*, end*/) { 137 | if (this === null || this === undefined) { 138 | throw new TypeError('this is null or not defined'); 139 | } 140 | var O = Object(this); 141 | var len = O.length >>> 0; 142 | var relativeTarget = target >> 0; 143 | var to = relativeTarget < 0 ? Math.max(len + relativeTarget, 0) : Math.min(relativeTarget, len); 144 | var relativeStart = start >> 0; 145 | var from = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len); 146 | var end = arguments[2]; 147 | var relativeEnd = end === undefined ? len : end >> 0; 148 | var f = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len); 149 | var count = Math.min(f - from, len - to); 150 | var direction = 1; 151 | if (from < to && to < (from + count)) { 152 | direction = -1; 153 | from += count - 1; 154 | to += count - 1; 155 | } 156 | while (count > 0) { 157 | if (from in O) { 158 | O[to] = O[from]; 159 | } 160 | else { 161 | delete O[to]; 162 | } 163 | from += direction; 164 | to += direction; 165 | count--; 166 | } 167 | return O; 168 | } }); 169 | } 170 | if (!Array.from) { 171 | Object.defineProperty(Array, 'from', { value: (function() { 172 | var toStr = Object.prototype.toString; 173 | var isCallable = function(fn) { 174 | return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; 175 | }; 176 | var toInteger = function(value) { 177 | var number = Number(value); 178 | if (isNaN(number)) { return 0; } 179 | if (number === 0 || !isFinite(number)) { return number; } 180 | return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); 181 | }; 182 | var maxSafeInteger = Math.pow(2, 53) - 1; 183 | var toLength = function(value) { 184 | var len = toInteger(value); 185 | return Math.min(Math.max(len, 0), maxSafeInteger); 186 | }; 187 | 188 | return function(arrayLike/*, mapFn, thisArg */) { 189 | var C = this; 190 | var items = Object(arrayLike); 191 | if (arrayLike === null || arrayLike === undefined) { 192 | throw new TypeError("Array.from requires an array-like object - not null or undefined"); 193 | } 194 | var mapFn = arguments.length > 1 ? arguments[1] : void undefined; 195 | var T; 196 | if (typeof mapFn !== 'undefined') { 197 | if (!isCallable(mapFn)) { 198 | throw new TypeError('Array.from: when provided, the second argument must be a function'); 199 | } 200 | if (arguments.length > 2) { 201 | T = arguments[2]; 202 | } 203 | } 204 | var len = toLength(items.length); 205 | var A = isCallable(C) ? Object(new C(len)) : new Array(len); 206 | var k = 0; 207 | var kValue; 208 | while (k < len) { 209 | kValue = items[k]; 210 | if (mapFn) { 211 | A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); 212 | } 213 | else { 214 | A[k] = kValue; 215 | } 216 | k += 1; 217 | } 218 | A.length = len; 219 | return A; 220 | }; 221 | }()) }); 222 | } 223 | if (!Array.of) { 224 | Object.defineProperty(Array, 'of', { value: function() { 225 | return Array.prototype.slice.call(arguments); 226 | } }); 227 | } 228 | /* String */ 229 | if (!String.prototype.startsWith) { 230 | Object.defineProperty(String.prototype, 'startsWith', { value: function(searchString, position){ 231 | position = position || 0; 232 | return this.substr(position, searchString.length) === searchString; 233 | } }); 234 | } 235 | if (!String.prototype.endsWith) { 236 | Object.defineProperty(String.prototype, 'endsWith', { value: function(searchString, position) { 237 | var subjectString = this.toString(); 238 | if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { 239 | position = subjectString.length; 240 | } 241 | position -= searchString.length; 242 | var lastIndex = subjectString.indexOf(searchString, position); 243 | return lastIndex !== -1 && lastIndex === position; 244 | } }); 245 | } 246 | if (!String.prototype.includes) { 247 | Object.defineProperty(String.prototype, 'includes', { value: function() { 248 | if (typeof arguments[1] === "number") { 249 | if (this.length < arguments[0].length + arguments[1].length) { 250 | return false; 251 | } 252 | else { 253 | return this.substr(arguments[1], arguments[0].length) === arguments[0]; 254 | } 255 | } 256 | else { 257 | return String.prototype.indexOf.apply(this, arguments) !== -1; 258 | } 259 | } }); 260 | } 261 | if (!String.prototype.repeat) { 262 | Object.defineProperty(String.prototype, 'repeat', { value: function(count) { 263 | var str = this.toString(); 264 | count = +count; 265 | if (count !== count) { 266 | count = 0; 267 | } 268 | if (count < 0) { 269 | throw new RangeError('repeat count must be non-negative'); 270 | } 271 | if (count === Infinity) { 272 | throw new RangeError('repeat count must be less than infinity'); 273 | } 274 | count = Math.floor(count); 275 | if (str.length === 0 || count === 0) { 276 | return ''; 277 | } 278 | // Ensuring count is a 31-bit integer allows us to heavily optimize the 279 | // main part. But anyway, most current (August 2014) browsers can't handle 280 | // strings 1 << 28 chars or longer, so: 281 | if (str.length * count >= 1 << 28) { 282 | throw new RangeError('repeat count must not overflow maximum string size'); 283 | } 284 | var rpt = ''; 285 | for (;;) { 286 | if ((count & 1) === 1) { 287 | rpt += str; 288 | } 289 | count >>>= 1; 290 | if (count === 0) { 291 | break; 292 | } 293 | str += str; 294 | } 295 | // Could we try: 296 | // return Array(count + 1).join(this); 297 | return rpt; 298 | } }); 299 | } 300 | if (!String.prototype.trim) { 301 | Object.defineProperty(String.prototype, 'trim', { value: function() { 302 | return this.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); 303 | } }); 304 | } 305 | if (!String.prototype.trimLeft) { 306 | Object.defineProperty(String.prototype, 'trimLeft', { value: function() { 307 | return this.toString().replace(/^[\s\xa0]+/, ''); 308 | } }); 309 | } 310 | if (!String.prototype.trimRight) { 311 | Object.defineProperty(String.prototype, 'trimRight', { value: function() { 312 | return this.toString().replace(/[\s\xa0]+$/, ''); 313 | } }); 314 | } 315 | /* Object */ 316 | if (!Object.keys) { 317 | Object.defineProperty(Object, 'keys', { value: (function () { 318 | var hasOwnProperty = Object.prototype.hasOwnProperty, 319 | hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), 320 | dontEnums = [ 321 | 'toString', 322 | 'toLocaleString', 323 | 'valueOf', 324 | 'hasOwnProperty', 325 | 'isPrototypeOf', 326 | 'propertyIsEnumerable', 327 | 'constructor' 328 | ], 329 | dontEnumsLength = dontEnums.length; 330 | return function (obj) { 331 | if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { 332 | throw new TypeError('Object.keys called on non-object'); 333 | } 334 | var result = []; 335 | for (var prop in obj) { 336 | if (hasOwnProperty.call(obj, prop)) { 337 | result.push(prop); 338 | } 339 | } 340 | if (hasDontEnumBug) { 341 | for (var i=0; i < dontEnumsLength; i++) { 342 | if (hasOwnProperty.call(obj, dontEnums[i])) { 343 | result.push(dontEnums[i]); 344 | } 345 | } 346 | } 347 | return result; 348 | }; 349 | })() }); 350 | } 351 | /* Generic methods */ 352 | var generic = global.hprose.generic; 353 | 354 | function genericMethods(obj, properties) { 355 | var proto = obj.prototype; 356 | for (var i = 0, len = properties.length; i < len; i++) { 357 | var property = properties[i]; 358 | var method = proto[property]; 359 | if (typeof method === 'function' && typeof obj[property] === 'undefined') { 360 | Object.defineProperty(obj, property, { value: generic(method) }); 361 | } 362 | } 363 | } 364 | genericMethods(Array, [ 365 | "pop", 366 | "push", 367 | "reverse", 368 | "shift", 369 | "sort", 370 | "splice", 371 | "unshift", 372 | "concat", 373 | "join", 374 | "slice", 375 | "indexOf", 376 | "lastIndexOf", 377 | "filter", 378 | "forEach", 379 | "every", 380 | "map", 381 | "some", 382 | "reduce", 383 | "reduceRight", 384 | "includes", 385 | "find", 386 | "findIndex" 387 | ]); 388 | genericMethods(String, [ 389 | 'quote', 390 | 'substring', 391 | 'toLowerCase', 392 | 'toUpperCase', 393 | 'charAt', 394 | 'charCodeAt', 395 | 'indexOf', 396 | 'lastIndexOf', 397 | 'include', 398 | 'startsWith', 399 | 'endsWith', 400 | 'repeat', 401 | 'trim', 402 | 'trimLeft', 403 | 'trimRight', 404 | 'toLocaleLowerCase', 405 | 'toLocaleUpperCase', 406 | 'match', 407 | 'search', 408 | 'replace', 409 | 'split', 410 | 'substr', 411 | 'concat', 412 | 'slice' 413 | ]); 414 | -------------------------------------------------------------------------------- /lib/common/ResultMode.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/common/ResultMode.js * 13 | * * 14 | * Hprose ResultMode for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | global.hprose.ResultMode = { 24 | Normal: 0, 25 | Serialized: 1, 26 | Raw: 2, 27 | RawWithEndTag: 3 28 | }; 29 | global.hprose.Normal = global.hprose.ResultMode.Normal; 30 | global.hprose.Serialized = global.hprose.ResultMode.Serialized; 31 | global.hprose.Raw = global.hprose.ResultMode.Raw; 32 | global.hprose.RawWithEndTag = global.hprose.ResultMode.RawWithEndTag; 33 | -------------------------------------------------------------------------------- /lib/common/TimeoutError.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * TimeoutError.js * 13 | * * 14 | * TimeoutError for Node.js. * 15 | * * 16 | * LastModified: Jul 17, 2015 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | function TimeoutError(message) { 22 | Error.call(this); 23 | this.message = message; 24 | this.name = TimeoutError.name; 25 | if (typeof Error.captureStackTrace === 'function') { 26 | Error.captureStackTrace(this, TimeoutError); 27 | } 28 | } 29 | 30 | TimeoutError.prototype = Object.create(Error.prototype); 31 | TimeoutError.prototype.constructor = TimeoutError; 32 | 33 | module.exports = TimeoutError; 34 | -------------------------------------------------------------------------------- /lib/common/isError.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/common/isError.js * 13 | * * 14 | * isError for Node.js. * 15 | * * 16 | * LastModified: Sep 11, 2015 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | var objectToString = Object.prototype.toString; 22 | var getPrototypeOf = Object.getPrototypeOf; 23 | var ERROR_TYPE = '[object Error]'; 24 | 25 | function isError(err) { 26 | if (err instanceof Error) { 27 | return true; 28 | } 29 | if (typeof err !== 'object') { 30 | return false; 31 | } 32 | while (err) { 33 | if (objectToString.call(err) === ERROR_TYPE) { 34 | return true; 35 | } 36 | err = getPrototypeOf(err); 37 | } 38 | return false; 39 | } 40 | 41 | module.exports = isError; 42 | -------------------------------------------------------------------------------- /lib/filter/JSONRPCClientFilter.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/filter/JSONRPCClientFilter.js * 13 | * * 14 | * jsonrpc client filter for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var Tags = global.hprose.Tags; 24 | var BytesIO = global.hprose.BytesIO; 25 | var Writer = global.hprose.Writer; 26 | var Reader = global.hprose.Reader; 27 | var JSON = global.JSON; 28 | 29 | var s_id = 1; 30 | 31 | function JSONRPCClientFilter(version) { 32 | this.version = version || '2.0'; 33 | } 34 | 35 | JSONRPCClientFilter.prototype.inputFilter = function inputFilter(data/*, context*/) { 36 | var json = BytesIO.toString(data); 37 | if (json.charAt(0) === '{') { 38 | json = '[' + json + ']'; 39 | } 40 | var responses = JSON.parse(json); 41 | var stream = new BytesIO(); 42 | var writer = new Writer(stream, true); 43 | for (var i = 0, n = responses.length; i < n; ++i) { 44 | var response = responses[i]; 45 | if (response.error) { 46 | stream.writeByte(Tags.TagError); 47 | writer.writeString(response.error.message); 48 | } 49 | else { 50 | stream.writeByte(Tags.TagResult); 51 | writer.serialize(response.result); 52 | } 53 | } 54 | stream.writeByte(Tags.TagEnd); 55 | return stream.bytes; 56 | }; 57 | 58 | JSONRPCClientFilter.prototype.outputFilter = function outputFilter(data/*, context*/) { 59 | var requests = []; 60 | var stream = new BytesIO(data); 61 | var reader = new Reader(stream, false, false); 62 | var tag = stream.readByte(); 63 | do { 64 | var request = {}; 65 | if (tag === Tags.TagCall) { 66 | request.method = reader.readString(); 67 | tag = stream.readByte(); 68 | if (tag === Tags.TagList) { 69 | request.params = reader.readListWithoutTag(); 70 | tag = stream.readByte(); 71 | } 72 | if (tag === Tags.TagTrue) { 73 | tag = stream.readByte(); 74 | } 75 | } 76 | if (this.version === '1.1') { 77 | request.version = '1.1'; 78 | } 79 | else if (this.version === '2.0') { 80 | request.jsonrpc = '2.0'; 81 | } 82 | request.id = s_id++; 83 | requests.push(request); 84 | } while (tag === Tags.TagCall); 85 | if (requests.length > 1) { 86 | return JSON.stringify(requests); 87 | } 88 | return JSON.stringify(requests[0]); 89 | }; 90 | 91 | global.hprose.JSONRPCClientFilter = JSONRPCClientFilter; 92 | -------------------------------------------------------------------------------- /lib/filter/JSONRPCServiceFilter.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/filter/JSONRPCServiceFilter.js * 13 | * * 14 | * jsonrpc service filter for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var Tags = global.hprose.Tags; 24 | var BytesIO = global.hprose.BytesIO; 25 | var Writer = global.hprose.Writer; 26 | var Reader = global.hprose.Reader; 27 | var JSON = global.JSON; 28 | 29 | var leftbrace = 0x7B; // '{' 30 | var leftbracket = 0x5B; // '[' 31 | 32 | function JSONRPCServiceFilter() {} 33 | 34 | JSONRPCServiceFilter.prototype.inputFilter = function inputFilter(data, context) { 35 | if (data.length > 0) { 36 | if (data[0] === leftbracket || data[0] === leftbrace) { 37 | var json = BytesIO.toString(data); 38 | if (json.charAt(0) === '{') { 39 | json = '[' + json + ']'; 40 | } 41 | var requests; 42 | try { 43 | requests = JSON.parse(json); 44 | } 45 | catch (e) { 46 | return data; 47 | } 48 | var bytes = new BytesIO(); 49 | var writer = new Writer(bytes, true); 50 | context.userdata.jsonrpc = []; 51 | for (var i = 0, n = requests.length; i < n; ++i) { 52 | var jsonrpc = {}; 53 | var request = requests[i]; 54 | if (request.id === undefined) { 55 | jsonrpc.id = null; 56 | } 57 | else { 58 | jsonrpc.id = request.id; 59 | } 60 | if (request.version) { 61 | jsonrpc.version = request.version; 62 | } 63 | else if (request.jsonrpc) { 64 | jsonrpc.version = request.jsonrpc; 65 | } 66 | else { 67 | jsonrpc.version = '1.0'; 68 | } 69 | context.userdata.jsonrpc[i] = jsonrpc; 70 | if (request.method) { 71 | bytes.writeByte(Tags.TagCall); 72 | writer.writeString(request.method); 73 | if (request.params && request.params.length > 0) { 74 | writer.writeList(request.params); 75 | } 76 | } 77 | } 78 | bytes.writeByte(Tags.TagEnd); 79 | data = bytes.bytes; 80 | } 81 | } 82 | return data; 83 | }; 84 | 85 | JSONRPCServiceFilter.prototype.outputFilter = function outputFilter(data, context) { 86 | if (context.userdata.jsonrpc) { 87 | var jsonrpc = context.userdata.jsonrpc; 88 | var responses = []; 89 | var stream = new BytesIO(data); 90 | var reader = new Reader(stream, false, false); 91 | var tag = stream.readByte(); 92 | var i = 0; 93 | do { 94 | var response = {}; 95 | var version = jsonrpc[i].version; 96 | if (version !== '2.0') { 97 | if (version === '1.1') { 98 | response.version = '1.1'; 99 | } 100 | response.result = null; 101 | response.error = null; 102 | } 103 | else { 104 | response.jsonrpc = '2.0'; 105 | } 106 | response.id = jsonrpc[i].id; 107 | if (tag === Tags.TagResult) { 108 | reader.reset(); 109 | response.result = reader.unserialize(); 110 | tag = stream.readByte(); 111 | } 112 | else if (tag === Tags.TagError) { 113 | reader.reset(); 114 | response.error = { 115 | code: -1, 116 | message: reader.readString() 117 | }; 118 | tag = stream.readByte(); 119 | } 120 | responses[i++] = response; 121 | } while (tag !== Tags.TagEnd); 122 | if (responses.length === 1) { 123 | responses = responses[0]; 124 | } 125 | data = JSON.stringify(responses); 126 | } 127 | return data; 128 | }; 129 | 130 | global.hprose.JSONRPCServiceFilter = JSONRPCServiceFilter; 131 | -------------------------------------------------------------------------------- /lib/hprose.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose.js * 13 | * * 14 | * hprose for Node.js. * 15 | * * 16 | * LastModified: Sep 30, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | global.hprose = global.hprose || Object.create(null); 24 | 25 | require('./common/Helper.js'); 26 | require('./common/Polyfill.js'); 27 | require('./common/HarmonyMaps.js'); 28 | require('./common/Future.js'); 29 | require('./common/ResultMode.js'); 30 | 31 | require('./io/BytesIO.js'); 32 | require('./io/ClassManager.js'); 33 | require('./io/Tags.js'); 34 | require('./io/Writer.js'); 35 | require('./io/Reader.js'); 36 | require('./io/Formatter.js'); 37 | 38 | require('./client/Client.js'); 39 | require('./client/HttpClient.js'); 40 | require('./client/SocketClient.js'); 41 | require('./client/WebSocketClient.js'); 42 | 43 | require('./server/Service.js'); 44 | require('./server/HttpService.js'); 45 | require('./server/HttpServer.js'); 46 | require('./server/SocketService.js'); 47 | require('./server/SocketServer.js'); 48 | require('./server/WebSocketService.js'); 49 | require('./server/WebSocketServer.js'); 50 | require('./server/Server.js'); 51 | 52 | require('./filter/JSONRPCClientFilter.js'); 53 | require('./filter/JSONRPCServiceFilter.js'); 54 | 55 | require('./utils/regenerator-runtime.js'); 56 | 57 | global.HproseCompleter = global.hprose.Completer; 58 | global.HproseFuture = global.hprose.Future; 59 | global.HproseResultMode = global.hprose.ResultMode; 60 | 61 | global.HproseBytesIO = global.hprose.BytesIO; 62 | global.HproseClassManager = global.hprose.ClassManager; 63 | global.HproseTags = global.hprose.Tags; 64 | global.HproseWriter = global.hprose.Writer; 65 | global.HproseRawReader = global.hprose.RawReader; 66 | global.HproseReader = global.hprose.Reader; 67 | global.HproseFormatter = global.hprose.Formatter; 68 | 69 | global.HproseClient = global.hprose.Client; 70 | global.HproseHttpClient = global.hprose.HttpClient; 71 | global.HproseSocketClient = global.hprose.SocketClient; 72 | global.HproseTcpClient = global.hprose.TcpClient; 73 | global.HproseUnixClient = global.hprose.UnixClient; 74 | global.HproseWebSocketClient = global.hprose.WebSocketClient; 75 | 76 | global.HproseService = global.hprose.Service; 77 | global.HproseServer = global.hprose.Server; 78 | global.HproseHttpService = global.hprose.HttpService; 79 | global.HproseHttpServer = global.hprose.HttpServer; 80 | global.HproseSocketService = global.hprose.SocketService; 81 | global.HproseSocketServer = global.hprose.SocketServer; 82 | global.HproseTcpServer = global.hprose.TcpServer; 83 | global.HproseUnixServer = global.hprose.UnixServer; 84 | global.HproseWebSocketService = global.hprose.WebSocketService; 85 | global.HproseWebSocketServer = global.hprose.WebSocketServer; 86 | 87 | global.HproseJSONRPCClientFilter = global.hprose.JSONRPCClientFilter; 88 | global.HproseJSONRPCServiceFilter = global.hprose.JSONRPCServiceFilter; 89 | 90 | global.hprose.common = { 91 | Completer: global.hprose.Completer, 92 | Future: global.hprose.Future, 93 | ResultMode: global.hprose.ResultMode 94 | }; 95 | 96 | global.hprose.io = { 97 | BytesIO: global.hprose.BytesIO, 98 | ClassManager: global.hprose.ClassManager, 99 | Tags: global.hprose.Tags, 100 | RawReader: global.hprose.RawReader, 101 | Reader: global.hprose.Reader, 102 | Writer: global.hprose.Writer, 103 | Formatter: global.hprose.Formatter 104 | }; 105 | 106 | global.hprose.client = { 107 | Client: global.hprose.Client, 108 | HttpClient: global.hprose.HttpClient, 109 | SocketClient: global.hprose.SocketClient, 110 | TcpClient: global.hprose.TcpClient, 111 | UnixClient: global.hprose.UnixClient, 112 | WebSocketClient: global.hprose.WebSocketClient 113 | }; 114 | 115 | global.hprose.server = { 116 | Service: global.hprose.Service, 117 | Server: global.hprose.Server, 118 | HttpService: global.hprose.HttpService, 119 | HttpServer: global.hprose.HttpServer, 120 | SocketService: global.hprose.SocketService, 121 | SocketServer: global.hprose.SocketServer, 122 | TcpServer: global.hprose.TcpServer, 123 | UnixServer: global.hprose.UnixServer, 124 | WebSocketService: global.hprose.WebSocketService, 125 | WebSocketServer: global.hprose.WebSocketServer 126 | }; 127 | 128 | global.hprose.filter = { 129 | JSONRPCClientFilter: global.hprose.JSONRPCClientFilter, 130 | JSONRPCServiceFilter: global.hprose.JSONRPCServiceFilter 131 | }; 132 | 133 | module.exports = global.hprose; 134 | -------------------------------------------------------------------------------- /lib/io/ClassManager.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/ClassManager.js * 13 | * * 14 | * hprose ClassManager for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var WeakMap = global.WeakMap; 24 | 25 | var classCache = Object.create(null); 26 | var aliasCache = new WeakMap(); 27 | 28 | function register(cls, alias) { 29 | aliasCache.set(cls, alias); 30 | classCache[alias] = cls; 31 | } 32 | 33 | function getClassAlias(cls) { 34 | return aliasCache.get(cls); 35 | } 36 | 37 | function getClass(alias) { 38 | return classCache[alias]; 39 | } 40 | 41 | global.hprose.ClassManager = Object.create(null, { 42 | register: { value: register }, 43 | getClassAlias: { value: getClassAlias }, 44 | getClass: { value: getClass } 45 | }); 46 | 47 | global.hprose.register = register; 48 | 49 | register(Object, 'Object'); 50 | -------------------------------------------------------------------------------- /lib/io/Formatter.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Formatter.js * 13 | * * 14 | * Hprose Formatter for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var BytesIO = global.hprose.BytesIO; 24 | var Writer = global.hprose.Writer; 25 | var Reader = global.hprose.Reader; 26 | 27 | function serialize(value, simple) { 28 | var stream = new BytesIO(); 29 | var writer = new Writer(stream, simple); 30 | writer.serialize(value); 31 | return stream; 32 | } 33 | 34 | function unserialize(stream, simple, useHarmonyMap) { 35 | if (!(stream instanceof BytesIO)) { 36 | stream = new BytesIO(stream); 37 | } 38 | return new Reader(stream, simple, useHarmonyMap).unserialize(); 39 | } 40 | 41 | global.hprose.Formatter = { 42 | serialize: function (value, simple) { 43 | return serialize(value, simple).bytes; 44 | }, 45 | unserialize: unserialize 46 | }; 47 | 48 | global.hprose.serialize = serialize; 49 | 50 | global.hprose.unserialize = unserialize; 51 | -------------------------------------------------------------------------------- /lib/io/Tags.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/io/Tags.js * 13 | * * 14 | * Hprose Tags for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | global.hprose.Tags = { 24 | /* Serialize Tags */ 25 | TagInteger : 0x69, // 'i' 26 | TagLong : 0x6C, // 'l' 27 | TagDouble : 0x64, // 'd' 28 | TagNull : 0x6E, // 'n' 29 | TagEmpty : 0x65, // 'e' 30 | TagTrue : 0x74, // 't' 31 | TagFalse : 0x66, // 'f' 32 | TagNaN : 0x4E, // 'N' 33 | TagInfinity : 0x49, // 'I' 34 | TagDate : 0x44, // 'D' 35 | TagTime : 0x54, // 'T' 36 | TagUTC : 0x5A, // 'Z' 37 | TagBytes : 0x62, // 'b' 38 | TagUTF8Char : 0x75, // 'u' 39 | TagString : 0x73, // 's' 40 | TagGuid : 0x67, // 'g' 41 | TagList : 0x61, // 'a' 42 | TagMap : 0x6d, // 'm' 43 | TagClass : 0x63, // 'c' 44 | TagObject : 0x6F, // 'o' 45 | TagRef : 0x72, // 'r' 46 | /* Serialize Marks */ 47 | TagPos : 0x2B, // '+' 48 | TagNeg : 0x2D, // '-' 49 | TagSemicolon : 0x3B, // ',' 50 | TagOpenbrace : 0x7B, // '{' 51 | TagClosebrace : 0x7D, // '}' 52 | TagQuote : 0x22, // '"' 53 | TagPoint : 0x2E, // '.' 54 | /* Protocol Tags */ 55 | TagFunctions : 0x46, // 'F' 56 | TagCall : 0x43, // 'C' 57 | TagResult : 0x52, // 'R' 58 | TagArgument : 0x41, // 'A' 59 | TagError : 0x45, // 'E' 60 | TagEnd : 0x7A // 'z' 61 | }; 62 | -------------------------------------------------------------------------------- /lib/server/HttpServer.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/HttpServer.js * 13 | * * 14 | * Hprose Http Server for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | var http = require('http'); 25 | var https = require('https'); 26 | var HttpService = global.hprose.HttpService; 27 | 28 | function HttpServer(port, hostname, tlsOptions) { 29 | HttpService.call(this); 30 | 31 | var self = this; 32 | var server = (tlsOptions ? 33 | https.createServer(tlsOptions, self.handle) : 34 | http.createServer(self.handle)); 35 | 36 | server.on('clientError', function (e, socket) { 37 | var context = { server: server, socket: socket, userdata:{} }; 38 | try { 39 | self.emit('sendError', e, context); 40 | if (self.onSendError) { 41 | self.onSendError(e, context); 42 | } 43 | } 44 | catch(e) {} 45 | }); 46 | 47 | function start() { 48 | server.listen(port, hostname); 49 | } 50 | function stop() { 51 | server.close(); 52 | } 53 | function listen() { 54 | server.listen.apply(server, arguments); 55 | } 56 | function close(callback) { 57 | server.close(callback); 58 | } 59 | 60 | Object.defineProperties(this, { 61 | server: { get: function () { return server; } }, 62 | start: { value: start }, 63 | stop: { value: stop }, 64 | listen: { value: listen }, 65 | close: { value: close } 66 | }); 67 | } 68 | 69 | util.inherits(HttpServer, HttpService); 70 | 71 | global.hprose.HttpServer = HttpServer; 72 | -------------------------------------------------------------------------------- /lib/server/HttpService.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/HttpService.js * 13 | * * 14 | * Hprose Http Service for Node.js. * 15 | * * 16 | * LastModified: Jun 6, 2018 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var fs = require('fs'); 24 | var util = require('util'); 25 | 26 | var Service = global.hprose.Service; 27 | var BytesIO = global.hprose.BytesIO; 28 | var Future = global.hprose.Future; 29 | 30 | function HttpService() { 31 | Service.call(this); 32 | 33 | var _onSendHeader = null; 34 | var _crossDomain = true; 35 | var _P3P = true; 36 | var _get = true; 37 | var _origins = {}; 38 | var _origincount = 0; 39 | var _crossDomainXmlFile = null; 40 | var _crossDomainXmlContent = null; 41 | var _clientAccessPolicyXmlFile = null; 42 | var _clientAccessPolicyXmlContent = null; 43 | var _lastModified = (new Date()).toUTCString(); 44 | var _etag = '"' + Math.floor(Math.random() * 2147483647).toString(16) + 45 | ':' + Math.floor(Math.random() * 2147483647).toString(16) + '"'; 46 | 47 | var self = this; 48 | 49 | function getSendHeader() { 50 | return _onSendHeader; 51 | } 52 | 53 | function setSendHeader(value) { 54 | if (value === null || typeof value === 'function') { 55 | _onSendHeader = value; 56 | } 57 | else { 58 | throw new Error('onSendHeader must be a function or null.'); 59 | } 60 | } 61 | 62 | function crossDomainXmlHandler(request, response) { 63 | if (request.url.toLowerCase() === '/crossdomain.xml') { 64 | if (request.headers['if-modified-since'] === _lastModified && 65 | request.headers['if-none-match'] === _etag) { 66 | response.statusCode = 304; 67 | } 68 | else { 69 | response.setHeader('Last-Modified', _lastModified); 70 | response.setHeader('Etag', _etag); 71 | response.setHeader('Content-Type', 'text/xml'); 72 | response.setHeader('Content-Length', _crossDomainXmlContent.length); 73 | response.write(_crossDomainXmlContent); 74 | } 75 | response.end(); 76 | return true; 77 | } 78 | return false; 79 | } 80 | 81 | function clientAccessPolicyXmlHandler(request, response) { 82 | if (request.url.toLowerCase() === '/clientaccesspolicy.xml') { 83 | if (request.headers['if-modified-since'] === _lastModified && 84 | request.headers['if-none-match'] === _etag) { 85 | response.statusCode = 304; 86 | } 87 | else { 88 | response.setHeader('Last-Modified', _lastModified); 89 | response.setHeader('Etag', _etag); 90 | response.setHeader('Content-Type', 'text/xml'); 91 | response.setHeader('Content-Length', _clientAccessPolicyXmlContent.length); 92 | response.write(_clientAccessPolicyXmlContent); 93 | } 94 | response.end(); 95 | return true; 96 | } 97 | return false; 98 | } 99 | 100 | function sendHeader(context) { 101 | var resp = context.response; 102 | resp.statusCode = 200; 103 | resp.setHeader('Content-Type', 'text/plain'); 104 | if (_P3P) { 105 | resp.setHeader('P3P', 106 | 'CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi ' + 107 | 'CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL ' + 108 | 'UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"'); 109 | } 110 | if (_crossDomain) { 111 | var origin = context.request.headers.origin; 112 | if (origin && origin !== 'null') { 113 | if (_origincount === 0 || _origins[origin]) { 114 | resp.setHeader('Access-Control-Allow-Origin', origin); 115 | resp.setHeader('Access-Control-Allow-Credentials', 'true'); 116 | } 117 | } 118 | else { 119 | resp.setHeader('Access-Control-Allow-Origin', '*'); 120 | } 121 | } 122 | self.emit('sendHeader', context); 123 | if (_onSendHeader !== null) { 124 | _onSendHeader(context); 125 | } 126 | } 127 | 128 | function isCrossDomainEnabled() { 129 | return _crossDomain; 130 | } 131 | 132 | function setCrossDomainEnabled(value) { 133 | _crossDomain = !!value; 134 | } 135 | 136 | function isP3PEnabled() { 137 | return _P3P; 138 | } 139 | 140 | function setP3PEnabled(value) { 141 | _P3P = !!value; 142 | } 143 | 144 | function isGetEnabled() { 145 | return _get; 146 | } 147 | 148 | function setGetEnabled(value) { 149 | _get = !!value; 150 | } 151 | 152 | function addAccessControlAllowOrigin(origin) { 153 | if (!_origins[origin]) { 154 | _origins[origin] = true; 155 | _origincount++; 156 | } 157 | } 158 | 159 | function removeAccessControlAllowOrigin(origin) { 160 | if (_origins[origin]) { 161 | delete _origins[origin]; 162 | _origincount--; 163 | } 164 | } 165 | 166 | function getCrossDomainXmlFile() { 167 | return _crossDomainXmlFile; 168 | } 169 | 170 | function setCrossDomainXmlFile(value) { 171 | _crossDomainXmlFile = value; 172 | _crossDomainXmlContent = fs.readFileSync(_crossDomainXmlFile); 173 | } 174 | 175 | function getCrossDomainXmlContent() { 176 | return _crossDomainXmlContent; 177 | } 178 | 179 | function setCrossDomainXmlContent(value) { 180 | _crossDomainXmlFile = null; 181 | if (typeof(value) === 'string') { value = new Buffer(value); } 182 | _crossDomainXmlContent = value; 183 | } 184 | 185 | function getClientAccessPolicyXmlFile() { 186 | return _clientAccessPolicyXmlFile; 187 | } 188 | 189 | function setClientAccessPolicyXmlFile(value) { 190 | _clientAccessPolicyXmlFile = value; 191 | _clientAccessPolicyXmlContent = fs.readFileSync(_clientAccessPolicyXmlFile); 192 | } 193 | 194 | function getClientAccessPolicyXmlContent() { 195 | return _clientAccessPolicyXmlContent; 196 | } 197 | 198 | function setClientAccessPolicyXmlContent(value) { 199 | _clientAccessPolicyXmlFile = null; 200 | if (typeof(value) === 'string') { value = new Buffer(value); } 201 | _clientAccessPolicyXmlContent = value; 202 | } 203 | 204 | function _send(data, response) { 205 | data = BytesIO.toBuffer(data); 206 | response.setHeader('Content-Length', data.length); 207 | response.end(data); 208 | } 209 | 210 | function send(data, response) { 211 | if (Future.isFuture(data)) { 212 | data.then(function(data) { _send(data, response); }); 213 | } 214 | else { 215 | _send(data, response); 216 | } 217 | } 218 | 219 | function handle(request, response) { 220 | var context = { 221 | server: self.server, 222 | request: request, 223 | response: response, 224 | socket: request.socket, 225 | userdata: {} 226 | }; 227 | request.socket.setTimeout(self.timeout); 228 | var bytes = new BytesIO(); 229 | var done = new Future(); 230 | request.on('data', function(data) { bytes.write(data); }); 231 | request.on('end', function() { 232 | if (_clientAccessPolicyXmlContent !== null && clientAccessPolicyXmlHandler(request, response)) { return; } 233 | if (_crossDomainXmlContent !== null && crossDomainXmlHandler(request, response)) { return; } 234 | try { 235 | sendHeader(context); 236 | } 237 | catch (e) { 238 | send(self.endError(e, context), response); 239 | done.resolve(true); 240 | return; 241 | } 242 | var result = ''; 243 | if ((request.method === 'GET') && _get) { 244 | result = self.doFunctionList(context); 245 | } 246 | else if (request.method === 'POST') { 247 | result = self.defaultHandle(bytes.bytes, context); 248 | } 249 | send(result, response); 250 | done.resolve(result); 251 | }); 252 | return done; 253 | } 254 | 255 | Object.defineProperties(this, { 256 | onSendHeader: { get: getSendHeader, set: setSendHeader }, 257 | crossDomain: { get: isCrossDomainEnabled, set: setCrossDomainEnabled }, 258 | p3p: { get: isP3PEnabled, set: setP3PEnabled }, 259 | get: { get: isGetEnabled, set: setGetEnabled }, 260 | crossDomainXmlFile: { get: getCrossDomainXmlFile, set: setCrossDomainXmlFile }, 261 | crossDomainXmlContent: { get: getCrossDomainXmlContent, set: setCrossDomainXmlContent }, 262 | clientAccessPolicyXmlFile: { get: getClientAccessPolicyXmlFile, set: setClientAccessPolicyXmlFile }, 263 | clientAccessPolicyXmlContent: { get: getClientAccessPolicyXmlContent, set: setClientAccessPolicyXmlContent }, 264 | addAccessControlAllowOrigin: { value: addAccessControlAllowOrigin }, 265 | removeAccessControlAllowOrigin: { value: removeAccessControlAllowOrigin }, 266 | handle: { value: handle } 267 | }); 268 | } 269 | 270 | util.inherits(HttpService, Service); 271 | 272 | global.hprose.HttpService = HttpService; 273 | -------------------------------------------------------------------------------- /lib/server/Server.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/Server.js * 13 | * * 14 | * Hprose Server for Node.js. * 15 | * * 16 | * LastModified: Aug 20, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var parse = require('url').parse; 24 | var HttpServer = global.hprose.HttpServer; 25 | var SocketServer = global.hprose.SocketServer; 26 | var WebSocketServer = global.hprose.WebSocketServer; 27 | 28 | function create(uri, tlsOptions, handler) { 29 | var parser = parse(uri); 30 | var protocol = parser.protocol; 31 | var options = {}; 32 | var port; 33 | if (protocol === 'http:' || 34 | protocol === 'https:') { 35 | port = parseInt(parser.port, 10); 36 | if (!port) { 37 | port = (protocol === 'http:' ? 80 : 443); 38 | } 39 | return new HttpServer(port, parser.hostname, tlsOptions); 40 | } 41 | if (protocol === 'tcp:' || 42 | protocol === 'tcp4:'|| 43 | protocol === 'tcp6:' || 44 | protocol === 'tcps:' || 45 | protocol === 'tcp4s:' || 46 | protocol === 'tcp6s:' || 47 | protocol === 'tls:') { 48 | if (parser.hostname) { 49 | options.host = parser.hostname; 50 | } 51 | if (parser.port) { 52 | options.port = parseInt(parser.port, 10); 53 | } 54 | return new SocketServer(options, tlsOptions); 55 | } 56 | if (protocol === 'unix:') { 57 | options.path = parser.path; 58 | return new SocketServer(options, tlsOptions); 59 | } 60 | if (protocol === 'ws:' || 61 | protocol === 'wss:') { 62 | port = parseInt(parser.port, 10); 63 | if (!port) { 64 | port = (protocol === 'http:' ? 80 : 443); 65 | } 66 | options.port = port; 67 | options.host = parser.hostname; 68 | if (parser.path) { 69 | options.path = parser.path; 70 | } 71 | return new WebSocketServer(options, tlsOptions, handler); 72 | } 73 | throw new Error('The ' + protocol + ' server isn\'t implemented.'); 74 | } 75 | 76 | function Server(uri, tlsOptions, handler) { 77 | return create(uri, tlsOptions, handler); 78 | } 79 | 80 | Object.defineProperty(Server, 'create', { value: create }); 81 | 82 | global.hprose.Server = Server; 83 | -------------------------------------------------------------------------------- /lib/server/SocketServer.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/SocketServer.js * 13 | * * 14 | * Hprose Socket Server for Node.js. * 15 | * * 16 | * LastModified: Mar 3, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | var net = require('net'); 25 | var tls = require('tls'); 26 | var SocketService = global.hprose.SocketService; 27 | 28 | function SocketServer(options, tlsOptions) { 29 | SocketService.call(this); 30 | var self = this; 31 | var server = (tlsOptions ? 32 | tls.createServer(tlsOptions, self.handle) : 33 | net.createServer(self.handle)); 34 | 35 | server.on('error', function (e) { 36 | var context = { server: server, userdata:{} }; 37 | try { 38 | self.emit('sendError', e, context); 39 | if (self.onSendError) { 40 | self.onSendError(e, context); 41 | } 42 | } 43 | catch(e) {} 44 | }); 45 | 46 | function start() { 47 | server.listen(options); 48 | } 49 | function stop() { 50 | server.close(); 51 | } 52 | function listen() { 53 | server.listen.apply(server, arguments); 54 | } 55 | function close(callback) { 56 | server.close(callback); 57 | } 58 | 59 | Object.defineProperties(this, { 60 | server: { get: function () { return server; } }, 61 | start: { value: start }, 62 | stop: { value: stop }, 63 | listen: { value: listen }, 64 | close: { value: close } 65 | }); 66 | 67 | } 68 | 69 | util.inherits(SocketServer, SocketService); 70 | 71 | global.hprose.SocketServer = SocketServer; 72 | global.hprose.TcpServer = SocketServer; 73 | global.hprose.UnixServer = SocketServer; 74 | -------------------------------------------------------------------------------- /lib/server/SocketService.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/SocketService.js * 13 | * * 14 | * Hprose Socket Service for Node.js. * 15 | * * 16 | * LastModified: Sep 17, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | 25 | var Service = global.hprose.Service; 26 | var BytesIO = global.hprose.BytesIO; 27 | var Future = global.hprose.Future; 28 | 29 | function noop() {} 30 | 31 | function SocketService() { 32 | Service.call(this); 33 | 34 | var _onAccept = null; 35 | var _onClose = null; 36 | 37 | var self = this; 38 | 39 | function getAccept() { 40 | return _onAccept; 41 | } 42 | 43 | function setAccept(value) { 44 | if (value === null || typeof value === 'function') { 45 | _onAccept = value; 46 | } 47 | else { 48 | throw new Error('onAccept must be a function or null.'); 49 | } 50 | } 51 | 52 | function getClose() { 53 | return _onClose; 54 | } 55 | 56 | function setClose(value) { 57 | if (value === null || typeof value === 'function') { 58 | _onClose = value; 59 | } 60 | else { 61 | throw new Error('onClose must be a function or null.'); 62 | } 63 | } 64 | 65 | function _send(socket, data, id) { 66 | var p = (id === null ? 4 : 8); 67 | var n = data.length; 68 | var buf = new Buffer(p + n); 69 | if (p === 8) { 70 | buf.writeInt32BE(n | 0x80000000, 0); 71 | buf.writeInt32BE(id, 4); 72 | } 73 | else { 74 | buf.writeUInt32BE(n, 0); 75 | } 76 | for (var i = 0; i < n; i++) { 77 | buf[i + p] = data[i]; 78 | } 79 | socket.write(buf); 80 | } 81 | 82 | function send(socket, data, id) { 83 | if (Future.isFuture(data)) { 84 | data.then(function(data) { _send(socket, data, id); }); 85 | } 86 | else { 87 | _send(socket, data, id); 88 | } 89 | } 90 | 91 | function run(socket, data, id) { 92 | var context = { 93 | server: self.server, 94 | socket: socket, 95 | userdata: {} 96 | }; 97 | data = self.defaultHandle(data, context); 98 | send(socket, data, id); 99 | } 100 | 101 | function receive(socket) { 102 | var bytes = new BytesIO(); 103 | var headerLength = 4; 104 | var dataLength = -1; 105 | var id = null; 106 | socket.on('data', function(chunk) { 107 | bytes.write(chunk); 108 | while (true) { 109 | if ((dataLength < 0) && (bytes.length >= headerLength)) { 110 | dataLength = bytes.readInt32BE(); 111 | if ((dataLength & 0x80000000) !== 0) { 112 | dataLength &= 0x7fffffff; 113 | headerLength = 8; 114 | } 115 | } 116 | if ((headerLength === 8) && (id === null) && (bytes.length >= headerLength)) { 117 | id = bytes.readInt32BE(); 118 | } 119 | if ((dataLength >= 0) && ((bytes.length - headerLength) >= dataLength)) { 120 | var data = bytes.read(dataLength); 121 | run(socket, data, id); 122 | bytes.trunc(); 123 | dataLength = -1; 124 | headerLength = 4; 125 | id = null; 126 | } 127 | else { 128 | break; 129 | } 130 | } 131 | }); 132 | } 133 | 134 | function handle(socket) { 135 | var context = { 136 | server: self.server, 137 | socket: socket, 138 | userdata: {} 139 | }; 140 | try { 141 | self.emit('accept', context); 142 | if (_onAccept) { _onAccept(context); } 143 | } 144 | catch(e) { 145 | socket.end(); 146 | return; 147 | } 148 | socket.on('close', function() { 149 | try { 150 | self.emit('close', context); 151 | if (_onClose) { _onClose(context); } 152 | } 153 | catch(e) {} 154 | }); 155 | socket.on('end', noop); 156 | socket.on('error', function(e) { 157 | try { 158 | if (e.code != "EPIPE") { 159 | self.emit('sendError', e, context); 160 | if (self.onSendError) { 161 | self.onSendError(e, context); 162 | } 163 | } 164 | } 165 | catch(e) {} 166 | }); 167 | socket.setTimeout(self.timeout); 168 | receive(socket); 169 | } 170 | Object.defineProperties(this, { 171 | onAccept: { get: getAccept, set: setAccept }, 172 | onClose: { get: getClose, set: setClose }, 173 | handle: { value: handle } 174 | }); 175 | } 176 | 177 | util.inherits(SocketService, Service); 178 | 179 | global.hprose.SocketService = SocketService; 180 | -------------------------------------------------------------------------------- /lib/server/WebSocketServer.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/WebSocketServer.js * 13 | * * 14 | * Hprose WebSocket Server for Node.js. * 15 | * * 16 | * LastModified: Aug 20, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | var ws = require('ws'); 25 | var http = require('http'); 26 | var https = require('https'); 27 | var WebSocketService = global.hprose.WebSocketService; 28 | 29 | function WebSocketServer(options, tlsOptions, handler) { 30 | WebSocketService.call(this); 31 | var self = this; 32 | if (!handler) handler = this.handle; 33 | var httpserver = tlsOptions ? 34 | https.createServer(tlsOptions, handler) : 35 | http.createServer(handler); 36 | var host = options.host; 37 | var port = options.port; 38 | delete options.host; 39 | delete options.port; 40 | options.server = httpserver; 41 | options.perMessageDeflate = false; 42 | var server = null; 43 | 44 | function onerror(e, socket) { 45 | var context = { 46 | httpserver: httpserver, 47 | server: self.server, 48 | userdata:{} 49 | }; 50 | if (socket) { context.socket = socket; } 51 | try { 52 | self.emit('sendError', e, context); 53 | if (self.onSendError) { 54 | self.onSendError(e, context); 55 | } 56 | } 57 | catch(e) {} 58 | } 59 | 60 | httpserver.on('clientError', onerror); 61 | 62 | function start() { 63 | httpserver.listen(port, host); 64 | server = new ws.Server(options); 65 | server.on('connection', self.wsHandle); 66 | server.on('error', onerror); 67 | } 68 | function stop() { 69 | server.close(); 70 | httpserver.close(); 71 | } 72 | function listen() { 73 | httpserver.listen.apply(httpserver, arguments); 74 | server = new ws.Server(options); 75 | server.on('connection', self.wsHandle); 76 | server.on('error', onerror); 77 | } 78 | function close(callback) { 79 | server.close(); 80 | httpserver.close(callback); 81 | } 82 | 83 | Object.defineProperties(this, { 84 | httpserver: { get: function () { return httpserver; } }, 85 | server: { get: function () { return server; } }, 86 | start: { value: start }, 87 | stop: { value: stop }, 88 | listen: { value: listen }, 89 | close: { value: close } 90 | }); 91 | } 92 | 93 | util.inherits(WebSocketServer, WebSocketService); 94 | 95 | global.hprose.WebSocketServer = WebSocketServer; 96 | -------------------------------------------------------------------------------- /lib/server/WebSocketService.js: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * hprose/server/WebSocketService.js * 13 | * * 14 | * Hprose WebSocket Service for Node.js. * 15 | * * 16 | * LastModified: Sep 30, 2016 * 17 | * Author: Ma Bingyao * 18 | * * 19 | \**********************************************************/ 20 | 21 | 'use strict'; 22 | 23 | var util = require('util'); 24 | 25 | var HttpService = global.hprose.HttpService; 26 | var BytesIO = global.hprose.BytesIO; 27 | var Future = global.hprose.Future; 28 | 29 | function WebSocketService() { 30 | HttpService.call(this); 31 | 32 | var _onAccept = null; 33 | var _onClose = null; 34 | 35 | var self = this; 36 | 37 | function getAccept() { 38 | return _onAccept; 39 | } 40 | 41 | function setAccept(value) { 42 | if (value === null || typeof value === 'function') { 43 | _onAccept = value; 44 | } 45 | else { 46 | throw new Error('onAccept must be a function or null.'); 47 | } 48 | } 49 | 50 | function getClose() { 51 | return _onClose; 52 | } 53 | 54 | function setClose(value) { 55 | if (value === null || typeof value === 'function') { 56 | _onClose = value; 57 | } 58 | else { 59 | throw new Error('onClose must be a function or null.'); 60 | } 61 | } 62 | 63 | function _send(ws, data, id) { 64 | var bytes = new BytesIO(); 65 | bytes.writeInt32BE(id); 66 | if (data.constructor === String) { 67 | bytes.writeString(data); 68 | } 69 | else { 70 | bytes.write(data); 71 | } 72 | try { 73 | ws.send(bytes.bytes, { 74 | binary: true, 75 | compress: false 76 | }); 77 | } 78 | catch (e) { 79 | ws.emit('error', e); 80 | } 81 | } 82 | 83 | function send(ws, data, id) { 84 | if (Future.isFuture(data)) { 85 | data.then(function(data) { _send(ws, data, id); }); 86 | } 87 | else { 88 | _send(ws, data, id); 89 | } 90 | } 91 | 92 | function wsHandle(ws) { 93 | var context = { 94 | httpserver: self.httpserver, 95 | server: self.server, 96 | websocket: ws, 97 | socket: ws._socket, 98 | userdata: {} 99 | }; 100 | try { 101 | self.emit('accept', context); 102 | if (_onAccept) { _onAccept(context); } 103 | } 104 | catch(e) { 105 | ws.close(); 106 | return; 107 | } 108 | ws.on('close', function() { 109 | try { 110 | self.emit('close',context); 111 | if (_onClose) { _onClose(context); } 112 | } 113 | catch(e) {} 114 | }); 115 | ws.on('error', function(e) { 116 | try { 117 | self.emit('sendError', e, context); 118 | if (self.onSendError) { 119 | self.onSendError(e, context); 120 | } 121 | } 122 | catch(e) {} 123 | }); 124 | ws.on('message', function(data) { 125 | var bytes = new BytesIO(data); 126 | var id = bytes.readInt32BE(); 127 | var request = bytes.read(bytes.length - 4); 128 | process.nextTick(function() { 129 | var context = { 130 | httpserver: self.httpserver, 131 | server: self.server, 132 | websocket: ws, 133 | socket: ws._socket, 134 | userdata: {} 135 | }; 136 | data = self.defaultHandle(request, context); 137 | send(ws, data, id); 138 | }); 139 | }); 140 | } 141 | Object.defineProperties(this, { 142 | onAccept: { get: getAccept, set: setAccept }, 143 | onClose: { get: getClose, set: setClose }, 144 | wsHandle: { value: wsHandle } 145 | }); 146 | } 147 | 148 | util.inherits(WebSocketService, HttpService); 149 | 150 | global.hprose.WebSocketService = WebSocketService; 151 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hprose", 3 | "version": "2.0.51", 4 | "homepage": "https://github.com/hprose/hprose-nodejs", 5 | "description": "hprose for node.js", 6 | "keywords": [ 7 | "hprose", 8 | "rpc", 9 | "webservice", 10 | "websocket", 11 | "http", 12 | "ajax", 13 | "json", 14 | "jsonrpc", 15 | "cross-language", 16 | "cross-platform", 17 | "cross-domain", 18 | "html5", 19 | "serialize", 20 | "serialization", 21 | "protocol", 22 | "web", 23 | "service", 24 | "framework", 25 | "library", 26 | "game", 27 | "communication", 28 | "middleware", 29 | "webapi", 30 | "async", 31 | "batch", 32 | "multicall", 33 | "future", 34 | "promise", 35 | "comet", 36 | "push", 37 | "pub-sub", 38 | "publish", 39 | "subscribe", 40 | "idempotent", 41 | "oneway", 42 | "promises-aplus" 43 | ], 44 | "author": { 45 | "name" : "Ma Bingyao", 46 | "email" : "mabingyao@gmail.com", 47 | "url": "http://hprose.com/" 48 | }, 49 | "directories": { 50 | "lib": "lib/" 51 | }, 52 | "main": "lib/hprose.js", 53 | "optionalDependencies": { "ws": ">=4.0.0" }, 54 | "devDependencies": { 55 | "promises-aplus-tests": "*" 56 | }, 57 | "scripts": { 58 | "aplus-tests": "promises-aplus-tests lib/hprose" 59 | }, 60 | "engines": { 61 | "node": "*" 62 | }, 63 | "repository": { 64 | "type": "git", 65 | "url": "https://github.com/hprose/hprose-nodejs.git" 66 | }, 67 | "bugs": { 68 | "url": "https://github.com/hprose/hprose-nodejs/issues", 69 | "email": "andot@hprose.com" 70 | }, 71 | "license" : "MIT" 72 | } 73 | --------------------------------------------------------------------------------