Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ var SERIALIZER_MAP = exports.SERIALIZER_MAP = {};
SERIALIZER_MAP[t] = 'Date';
});

[
'reply'
].forEach(function (t) {
SERIALIZER_MAP[t] = "Reply";
});

// http://www.devthought.com/2011/12/22/a-string-is-not-an-error/
function JavaExceptionError(obj, withType) {
Error.call(this);
Expand Down
53 changes: 51 additions & 2 deletions lib/v1/decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ proto._readSparseObject = function (withType) {
label = this.byteBuffer.getChar(this.byteBuffer.position());
}
// skip 'z' char
this.byteBuffer.position(this.byteBuffer.position() + 1);
this.byteBuffer.skip(1);

// default type info
if (withType) {
Expand Down Expand Up @@ -461,7 +461,7 @@ proto._readNoLengthArray = function (withType, type) {
label = this.byteBuffer.getChar(this.byteBuffer.position());
}
// skip 'z' char
this.byteBuffer.position(this.byteBuffer.position() + 1);
this.byteBuffer.skip(1);

arr = withType
? { $class: type, $: arr }
Expand Down Expand Up @@ -561,6 +561,55 @@ utils.addByteCodes(BYTE_CODES, [
0x52,
], 'readRef');

/**
* read an call from buffer
*
* v1.0
* ```
* call ::= c(x63) x01 x00 header* m b16 b8 method-string (object)* z
* ```
*
* @return {Object}
* @api public
*/
proto.readCall = function(withType) {
this._checkLabel('readCall', 'c');

if (this.byteBuffer.get() !== 0x01 || this.byteBuffer.get() !== 0x00) {
new TypeError('hessian call error, expect code: 0x01 0x00');
}


var header = {};
var args = [];
var result = {header: header, arguments: args};

while (this.byteBuffer.getChar(this.byteBuffer.position()) === 'H') {
this.byteBuffer.position(this.byteBuffer.position() + 1); //skip 'H' char
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.byteBuffer.skip(1)

var key = this.byteBuffer.readRawString( this.byteBuffer.getUInt16() );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

括号里面前后空格去掉吧

header[key] = this.read(withType);
}

this._checkLabel('readCall.method', 'm');
var methodLength = this.byteBuffer.getUInt16();
result.method = this.byteBuffer.readRawString(methodLength);

//
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

去掉没用到的注释

var label = this.byteBuffer.getChar(this.byteBuffer.position());
while (label !== 'z') {
args.push(this.read(withType));
label = this.byteBuffer.getChar(this.byteBuffer.position());
}
// skip 'z' char
this.byteBuffer.skip(1);

return result;
};

utils.addByteCodes(BYTE_CODES, [
0x63,
], 'readCall');

/**
* read any thing
*
Expand Down
72 changes: 72 additions & 0 deletions lib/v1/encoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -512,4 +512,76 @@ proto.write = function (val) {
return this[method](val);
};

/**
* encode fault
* @param {fault} The defined fields are code, message, and detail. code is one of a short list of strings defined below. message is a user-readable message. detail is an object representing the exception. In Java, detail will be a serialized exception.
* @return {this}
*/
proto._writeFault = function(fault) {
this._assertType('writeFault', 'object', fault);

this._assertType('writeFault', 'string', fault.message);

var code = fault.code || 'ServiceException';

this.byteBuffer.putChar('f');
this.writeString('code');
this.writeString(code);
this.writeString('message');
this.writeString(fault.message);
if (fault.detail) {
this.writeString('detail');
this.writeObject(fault.detail);
}
return this;
};

proto._writeHeader = function(header) {
this._assertType('writeHeader', 'object', header);
this.byteBuffer.putChar('H');

if (SUPPORT_ES6_MAP && header instanceof Map) {
header.forEach(function (value, key) {
this.write(key);
this.write(value);
}, this);
} else {
var keys = Object.keys(header).sort();
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
this.writeString(k);
this.write(header[k]);
}
}
this.byteBuffer.putChar('z');
return this;
};

/**
* encode reply
* v1.0
* ```
* valid-reply ::= r x01 x00 header* object z
* fault-reply ::= r x01 x00 header* fault z
* ```
* @param {reply}
* @return {this}
*/
proto.writeReply = function(reply) {
this.byteBuffer.putChar('r').put(0x01).put(0x00);
if (reply.header) {
this._writeHeader(reply.header);
}

if (reply.fault) {
this._writeFault(reply.fault);
}else {
this.write(reply.value);
}

this.byteBuffer.putChar('z');
return this;
};


module.exports = Encoder;
113 changes: 113 additions & 0 deletions test/call-reply.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*!
* hessian.js - test/call-reply.test.js
*
* Copyright(c) 2016
* MIT Licensed
*
* Authors:
* tangzhi <[email protected]> (http://github.com/tangzhi)
*/

"use strict";

/**
* Module dependencies.
*/

var should = require('should');
var hessian = require('../');
var utils = require('./utils');

describe('call-reply.test.js', function () {
//c x01 x00
// m x00 x04 add2
// I x00 x00 x00 x02
// I x00 x00 x00 x03
// z
var simpleBuffer = Buffer.concat([
new Buffer(['c'.charCodeAt(0), 0x01, 0x00]),
new Buffer(['m'.charCodeAt(0), 0x00, 0x04]), new Buffer('add2'),
new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x00, 0x02]),
new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x00, 0x03]),
new Buffer('z')
]);

it('should read call [add2(2,3)]', function () {
hessian.decode(simpleBuffer).should.eql({
method: 'add2',
header: {},
arguments: [2,3]
});
});

it('should write reply 5', function() {
var buf = hessian.encode({$class:"reply", $:{value: 5}});
buf.should.be.a.Buffer;
// r x01 x00
// I x00 x00 x00 x05
// z
buf.should.eql(Buffer.concat([
new Buffer(['r'.charCodeAt(0), 0x01, 0x00]),
new Buffer(['I'.charCodeAt(0), 0x00, 0x00, 0x00, 0x05]),
new Buffer('z')
]));
});

it('should write reply fault', function() {
var fault = {
message: 'time out'
};
var buf = hessian.encode({$class:"reply", $:{fault: fault}});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

只有 encode,decode 的测试用例呢?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我添加的代码不是双向的,我是按需添加的。
在decode里,我只实现了call;在encode里,我只实现了reply。
修改后的代码,测试了下和我现有环境能对接上,就没再完善了...

buf.should.be.a.Buffer;
// r x01 x00
// f
// S x00 x04 code
// S x00 x10 ServiceException
// S x00 x07 message
// S x00 x08 time out
// z
buf.should.eql(Buffer.concat([
new Buffer(['r'.charCodeAt(0), 0x01, 0x00]),
new Buffer('f'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x04]), new Buffer('code'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x10]), new Buffer('ServiceException'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x07]), new Buffer('message'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x08]), new Buffer('time out'),
new Buffer('z')
]));
});

it('should write reply fault with detail', function() {
var fault = {
message : 'time out',
detail : {
$class : 'java.io.FileNotFoundException',
$: {}
}
};
var buf = hessian.encode({$class:"reply", $:{fault: fault}});
buf.should.be.a.Buffer;
// r x01 x00
// f
// S x00 x04 code
// S x00 x10 ServiceException
// S x00 x07 message
// S x00 x08 time out
// S x00 x06 detail
// M t x00 x1d java.io.FileNotFoundException
// z
// z
buf.should.eql(Buffer.concat([
new Buffer(['r'.charCodeAt(0), 0x01, 0x00]),
new Buffer('f'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x04]), new Buffer('code'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x10]), new Buffer('ServiceException'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x07]), new Buffer('message'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x08]), new Buffer('time out'),
new Buffer(['S'.charCodeAt(0), 0x00, 0x06]), new Buffer('detail'),
new Buffer(['M'.charCodeAt(0), 't'.charCodeAt(0), 0x00, 0x1d]), new Buffer('java.io.FileNotFoundException'),
new Buffer('zz')
]));
});

});