Decompressing data received as binary data in lambda - incorrect header check - node.js

I want to send compressed data (gzip) to some URL that will trigger a (proxy) lambda function, that will decompress the data.
The lambda function (NodeJS 8):
let zlib = require('zlib');
exports.handler = async (event) => {
let decompressedData = zlib.gunzipSync(event['body'])
return {
"statusCode": 200,
"body": decompressedData.toString()
};
};
I trigger it with a curl command to the URL (through API gateway), for some file that I compressed example.gz with gzip:
curl -X POST --data-binary #example.gz https://URL...
As a result, I get:
{"message": "Internal server error"}
And the error is (logs in Cloudwatch):
"errorMessage": "incorrect header check",
"errorType": "Error",
"stackTrace": [
"Gunzip.zlibOnError (zlib.js:153:15)",
"Gunzip._processChunk (zlib.js:411:30)",
"zlibBufferSync (zlib.js:144:38)",
"Object.gunzipSync (zlib.js:590:14)",
"exports.handler (/var/task/test_index.js:5:33)"
]
When I looked at the event['body'] itself, I see the exact data as I see in example.gz. Perhaps I need some special header? I just want to pass the data as is.

as Michael - sqlbot said, By default, API Gateway can't pass binary data into a Lambda function.
What worked for me:
I added the header Content-Type: application/octet-stream in the curl command, and in the API gateway settings, on Binary Media Types I added application/octet-stream.
This way, the data is passed in base64, and afterwards I just converted the date that is in base64 to a buffer:
let data = Buffer.from(event['body'], "base64")
And afterwards just decompress it.
For more information read here

1/ First you need to build your gzip correctly, ensure that gzip file header is not present : curl command a gzipped POST body to an apache server
Wrong way :
echo '{ "mydummy" : "json" }' > body
gzip body
hexdump -C body.gz
00000000 1f 8b 08 08 20 08 30 59 00 03 62 6f 64 79 00 ab |.... .0Y..body..|
00000010 56 50 ca ad 4c 29 cd cd ad 54 52 b0 52 50 ca 2a |VP..L)...TR.RP.*|
00000020 ce cf 53 52 a8 e5 02 00 a6 6a 24 99 17 00 00 00 |..SR.....j$.....|
00000030
Good way :
echo '{ "mydummy" : "json" }' | gzip > body.gz
hexdump -C body.gz
00000000 1f 8b 08 00 08 0a 30 59 00 03 ab 56 50 ca ad 4c |......0Y...VP..L|
00000010 29 cd cd ad 54 52 b0 52 50 ca 2a ce cf 53 52 a8 |)...TR.RP.*..SR.|
00000020 e5 02 00 a6 6a 24 99 17 00 00 00 |....j$.....|
0000002b
2/ In curl don't forget to specify the content-encoding with
-H "Content-Encoding: gzip"
3/ In addition if you use express+compress you don't need to call zlib
curl -X POST "http://example.org/api/a" -H "Content-Encoding: gzip" -H "Content-Type: application/json" --data-binary #body.gz
router.post("/api/a", function(req, res){
console.log(req.body); // { mydummy: 'json' }
});

Related

Use net Write to send data\r\n is sent as a string instead of eof

I want use socket send 'info\r\n' to redis server by net, send data is 69 6e 66 6f 5c 72 5c 6e
but i want send data is 69 6e 66 6f 0d 0a,\r\n treated as an string and wrong becomes 5c 72 5c 6e
send data is string in code i turn string to []byte and conn.write
This sending seems to be wrong, what is the correct sending method?
Your data 69 6e 66 6f 5c 72 5c 6e is:
b := []byte{0x69, 0x6e, 0x66, 0x6f, 0x5c, 0x72, 0x5c, 0x6e}
fmt.Printf("%q\n", string(b))
Which outputs:
"info\\r\\n"
It contains a backslash, an r, another backslash and an n character at the end.
You want to send a carriage return \r and a newline character \n, you don't have to send these "literally". \r and \n are single byte data, not 2-character sequences.
Your data should be:
b = []byte{0x69, 0x6e, 0x66, 0x6f, '\r', '\n'}
fmt.Printf("%q\n", string(b))
Which outputs:
"info\r\n"
Or simply:
b = []byte("info\r\n")
fmt.Printf("%q\n", string(b))
Which outputs the same. Try the examples on the Go Playground.
Know that the string literal "info\r\n" is an interpreted string literal, \r and \n sequences in it will be interpreted as single characters (the carriage return and newline characters). This is detailed in Spec: String literals.

What does read(0) in node stream do?

Could anyone illustrate how read(0) in node stream works, and in which case it is necessary?
The official read(0) doc is here. It says:
There are some cases where it is necessary to trigger a refresh of the underlying readable stream mechanisms, without actually consuming any data. In such cases, it is possible to call readable.read(0), which will always return null.
I met one case where read(0) is necessary. It is from stream-handbook. The source code is:
process.stdin.on('readable', function () {
var buf = process.stdin.read(3);
console.dir(buf);
process.stdin.read(0);
});
The result is:
$ (echo abc; sleep 1; echo def; sleep 1; echo ghi) | node consume2.js
<Buffer 61 62 63>
<Buffer 0a 64 65>
<Buffer 66 0a 67>
<Buffer 68 69 0a>
Comment out the read(0) sentence,
process.stdin.on('readable', function () {
var buf = process.stdin.read(3);
console.dir(buf);
// process.stdin.read(0);
});
The result would be:
$ (echo abc; sleep 1; echo def; sleep 1; echo ghi) | node consume1.js
<Buffer 61 62 63>
<Buffer 0a 64 65>
<Buffer 66 0a 67>
I experimented with the above code and found that if I removed sleep 1 from the subshell command, then read(0) sentence is not necessary.
I think here the subshell sends a 'end of stream' event to consumer1.js after sending ghi, but it seems consumer1.js does not receive the 'end of stream' event unless read(0) does something. When read(0) does something, the js file knows there is an'end of stream', and the readable is triggered once more.
So my questions are:
What is read(0) doing here?
Why does read(0) become unnecessary when sleep 1 is removed from the shell command
Can any one provide more cases where read(0) is necessary? (I tried file stream instead of stdin as js file input, then read(0) is not necessary)
Thanks.

Output matched string through end of tab-indented section?

Sample code from pci.ids below. I want to use the class code from lspci (lets say it's 0580) and have it navigate to C 05 > 80: Memory controller. I feel the most appropriate way (to avoid returning a value from the wrong class) is to just cut the section of C 05 first, then look for 80. Grep -A... will return everything after, and therefore if the 80 doesn't match something in C05 it would jump down to some Cn which contains an 80 element.
C 03 Display controller
00 VGA compatible controller
00 VGA controller
01 8514 controller
01 XGA compatible controller
02 3D controller
80 Display controller
C 04 Multimedia controller
00 Multimedia video controller
01 Multimedia audio controller
02 Computer telephony device
03 Audio device
80 Multimedia controller
C 05 Memory controller
00 RAM memory
01 FLASH memory
80 Memory controller
C 06 Bridge
00 Host bridge
01 ISA bridge
02 EISA bridge
03 MicroChannel bridge
04 PCI bridge
00 Normal decode
01 Subtractive decode
05 PCMCIA bridge
To pass "0580" into the awk program:
awk -v value='0580' '
BEGIN {a = substr(value,1,2); b = substr(value,3,2)}
$1 == "C" { p = ($2 == a)}
p && $1 == b {print; exit}
' file
If the first word is "C", set a boolean to true if the second word is "05".
If the flag is true and the first word is "80", print the current line and exit.

avr-gcc link error with independent obj

a little project of avr, when i directly compile main.c(all other c are included in main.c), all ok.
avr-gcc -Wall -mmcu=atmega8 -g -O1 $1 -o $1.out
avr-objdump -dS $1.out>$1.asm
with asm, i can see all vector here.
main.c.out: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 1d cd rjmp .-1478 ; 0xfffffa3c <__eeprom_end+0xff7efa3c>
2: 37 cd rjmp .-1426 ; 0xfffffa72 <__eeprom_end+0xff7efa72>
when i compile each c into obj (just add some header files, codes almost same), then link them, the result fail. of course MCU become mad.
for i in src/*.c; do j=`basename $i`; j=obj/${j%%.c}.o; avr-gcc -c $i -o $j -mmcu=atmega8 -g -O1 -Wall; done;
avr-ld obj/*.o -o a.out;
avr-objdump -dS a.out >a.asm;
here is code in asm, not vector jump here, but just my rom datas.
Disassembly of section .text:
00000000 <tm_tone>:
0: 00 00 e0 1d 9e 1a b5 17 62 16 ee 13 c1 11 d0 0f ........b.......
00000010 <tiger>:
10: 31 32 33 31 31 32 33 31 33 34 35 30 33 34 35 30 1231123134503450
any advise? thanks. if i need special each obj file manually when use avr-ld?
only this can be ok, after compile to obj. link use avr-gcc.
avr-gcc -Wall -mmcu=atmega8 -g -O1 -o main.o src/main.c obj/usart.o obj/irda.o obj/everybody.o obj/audio.o

elf file thinks its small, but its large! can not generate .bin and .hex files

I am working on migrating a project from Kail to Gcc.
Makefile http://www.copypastecode.com/73860/
.ld file http://www.copypastecode.com/73856/
I have a Makefile and a platform.ld script and some .c and .h files.
When i make, everything compiles and links and it looks good.
arm-none-eabi-size -B Output/stm32_gps_test.elf
text data bss dec hex filename
0 0 2048 2048 800 Output/stm32_gps_test.elf
but when i check the generated files i see this:
ls Output/
7327274 2011-07-02 04:28 stm32_gps_test.elf
0 2011-07-02 04:28 stm32_gps_test.bin
34 2011-07-02 04:28 stm32_gps_test.hex
and:
tail Output/stm32_gps_test.hex
:0400000508000000EF
:00000001FF
Some info on the elf file:
arm-none-eabi-readelf -h Output/stm32_gps_test.elf
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x8000000
Start of program headers: 52 (bytes into file)
Start of section headers: 7323752 (bytes into file)
Flags: 0x5000002, has entry point, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 40 (bytes)
Number of section headers: 18
Section header string table index: 15
What is wrong? i have tried to run objcopy to create a binfile and hexfile but the result is always the same.
When you disassemble it what do you see? (objdump -D) If you have for example a rom image at 0x80000000 and ram at 0x20000000 the .bin file from objcopy will be at a minimum 0x60000000 bytes plus the size of the image in rom. The intel hex file or srec should work though.
Does the option --set-section-flags .bss=alloc,load,contents works? With this option, the .bss section will be included in stm32_gps_test.bin.

Resources