Created
January 11, 2014 07:53
-
-
Save siteshen/8368248 to your computer and use it in GitHub Desktop.
Nginx user_id encoder/decoder from http://stackoverflow.com/a/19037624/739667
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # http://stackoverflow.com/a/19037624/739667 | |
| import base64 | |
| import socket | |
| import struct | |
| def decode_cookie(cookie): | |
| """decode a u cookie into an uid | |
| :param cookie: a cookie value that will be decoded into a uid | |
| :return: string representing the uid | |
| This algorithm is for version 2 of http://wiki.nginx.org/HttpUseridModule. | |
| This nginx module follows the apache mod_uid module algorithm, which is | |
| documented here: http://www.lexa.ru/programs/mod-uid-eng.html. | |
| """ | |
| # get the raw binary value | |
| binary_cookie = base64.b64decode(cookie) | |
| # unpack into 4 parts, each a network byte orderd 32 bit unsigned int | |
| unsigned_ints = struct.unpack('!4I', binary_cookie) | |
| # convert from network (big-endian) to host byte (probably little-endian) order | |
| host_byte_order_ints = [socket.ntohl(i) for i in unsigned_ints] | |
| # convert to upper case hex value | |
| uid = 'u=' + ''.join(['{0:08X}'.format(h) for h in host_byte_order_ints]) | |
| return uid | |
| def encode_uid(uid): | |
| """encode an uid into a u cookie | |
| :param uid: an uid that will be encoded into a cookie. | |
| :return: string representing the u cookie | |
| The algorithm is for version 2 of http://wiki.nginx.org/HttpUseridModule. | |
| This nginx module follows the apache mod_uid module algorithm, which is | |
| documented here: http://www.lexa.ru/programs/mod-uid-eng.html. | |
| """ | |
| # get the hex value of the uid | |
| hex_value = uid.split('=')[1] | |
| # convert 128 bit string into 4 32 bit integers | |
| host_byte_order_ints = [int(hex_value[i:i+8], 16) for i in range(0, 32, 8)] | |
| # convert from host byte (probably little-endian) to network byte (big-endian) order | |
| unsigned_ints = [socket.htonl(i) for i in host_byte_order_ints] | |
| # convert to raw binary value | |
| binary_cookie = struct.pack('!4I', *unsigned_ints) | |
| # get the base64 version of the cookie | |
| cookie = base64.b64encode(binary_cookie) | |
| return cookie |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment