This repository has been archived by the owner on Aug 5, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Forked from our internal code - Added a README - Added a few cats Meowbify goes open source!
- Loading branch information
Ryan J Daw
committed
Jul 6, 2012
0 parents
commit 5fd8bd0
Showing
23 changed files
with
1,786 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules/ | ||
*.swp | ||
.DS_Store | ||
*.bak | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
deps: | ||
npm install . |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
web: node web.js |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
Meowbify | ||
============== | ||
|
||
Meowbify is a Node.js super-webscale kitten-powered Coffeescript-infused evented based streaming cat injecting proxy. | ||
|
||
Think CloudFlare, but with Cats. | ||
|
||
[Check it out live](http://www.meowbify.com/) | ||
|
||
|
||
Meowbifiwhat is it? | ||
-------------------- | ||
|
||
This proxy is designed to insert tags, and also rewrite links, headers, cookies, etc | ||
so it appears to transparently work as a man in the middle. | ||
|
||
It also inserts Cats, courtesy of [The Cat API](http://thecatapi.com/). | ||
|
||
The proxy is designed to run on a wildcard domain *.SUFFIX_DOMAIN, and everything | ||
are rewritten to match that domain. | ||
|
||
To support HTTP and HTTPS sites, we use a prefix usually cat.* or cats.*. | ||
|
||
It currently only support origin sites running on ports :80 and :443. | ||
|
||
|
||
Configuration | ||
-------------- | ||
|
||
These can be set by environment variables: | ||
|
||
*PORT* | ||
: Port proxy listens on | ||
Default: 5000 | ||
|
||
*EXTERNAL_PORT* | ||
: Port proxy appears to be listening on (eg, the front-end server) | ||
Default: 80 | ||
|
||
*SUFFIX_DOMAIN* | ||
: Domain that is appended when rewritting links | ||
Default: 'meowbify.com' | ||
|
||
*PREFIX_SUBDOMAIN* | ||
: The subdomain that is prefix to mark http and https sites. | ||
Default: "cat" (which means cat.* == http, cats.* == https). | ||
|
||
*LOG_FORMAT* | ||
: Connect Middleware style log format | ||
Default: ':method :status :response-time \t:req[Host]:url :user-agent' | ||
|
||
|
||
Special Thanks | ||
-------------- | ||
|
||
The Mobify Team: | ||
|
||
- @fractaltheory who christened it "Meowbify" | ||
- @kpeatt who butched^Hbeautifully altered Mobify's logo in to a Cat | ||
- @shawnjan8 who squatted the domain | ||
- @rrjamie who wasted several afternoons of time to write it | ||
- @mobify whose time and money @rrjamie was wasting | ||
|
||
Also thanks to @AdenForshaw, who built the CatAPI. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"author": "Mobify <dev@mobify.com> (https://github.com/mobify)", | ||
"name": "meowbify", | ||
"description": "Injects Cats in to Pages", | ||
"version": "0.0.1", | ||
"homepage": "https://www.meowbify.com/", | ||
"main": "lib/main.js", | ||
"dependencies": { | ||
"htmlparser": "git+https://github.com/mobify/node-htmlparser.git#v1.x", | ||
"coffee-script": "~1.3.3", | ||
"request": "~2.9.202", | ||
"connect": "2.3.3", | ||
"underscore": "~1.3.3" | ||
}, | ||
"devDependencies": {}, | ||
"optionalDependencies": {}, | ||
"engines": { | ||
"node": "0.6.x" | ||
}, | ||
"private": true | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
Stream = require 'stream' | ||
|
||
### | ||
BufferStream | ||
A streaming interface for a buffer. | ||
You can stream (eg, `pipe`) data in to a `BufferStream` object | ||
and then `pipe` it into another object. | ||
BufferStreams have a few benefits: | ||
- Automatically buffer any amount of data (memory permitting). | ||
- Automatically increase in size in a semi-intelligent fashion. | ||
- No need to wait for `drain` on the write side. | ||
- Makes efficient use of buffers | ||
- You can `pause` a BufferStream and collect data for later. | ||
### | ||
|
||
class BufferStream extends Stream | ||
MIN_BUFFER_SIZE = 4096 | ||
MAX_BUFFER_SIZE = MIN_BUFFER_SIZE * 16 | ||
|
||
constructor: (size = MIN_BUFFER_SIZE) -> | ||
@writeIndex = 0 | ||
@readIndex = 0 | ||
@buffer = new Buffer(size) | ||
|
||
@readBuffer = 1024*16 | ||
|
||
@encoding = 'utf8' | ||
@emitStrings = false | ||
|
||
|
||
# Writing | ||
@_endWrite = false | ||
@_endRead = false | ||
|
||
@_destroySoon = false | ||
@_destroyed = false | ||
|
||
@writable = true | ||
@readable = true | ||
|
||
@paused = false | ||
|
||
|
||
### | ||
# | ||
### | ||
ensureSpace: (bytes) -> | ||
bytesAvailable = @buffer.size - @writeIndex | ||
|
||
# Current buffer might be large enough | ||
if bytesAvailable >= bytes | ||
return | ||
|
||
# Allocate new buffer | ||
currentSize = @writeIndex - @readIndex | ||
desiredSize = currentSize + bytes | ||
|
||
targetSize = MIN_BUFFER_SIZE | ||
while targetSize < desiredSize | ||
targetSize *= 2 | ||
|
||
# Copying to a new buffer prevents mangling of buffers | ||
# that were returned by _read. | ||
newBuffer = new Buffer targetSize | ||
@buffer.copy newBuffer, 0, @readIndex, @writeIndex | ||
@writeIndex = @writeIndex - @readIndex | ||
@readIndex = 0 | ||
|
||
@buffer = newBuffer | ||
|
||
true | ||
|
||
### | ||
# Internal Buffer Access | ||
### | ||
_writeBuffer: (buffer) -> | ||
@ensureSpace buffer.length | ||
buffer.copy @buffer, @writeIndex | ||
@writeIndex = @writeIndex + buffer.length | ||
|
||
true | ||
|
||
_writeString: (string) -> | ||
bytes = Buffer.byteLength string, @encoding | ||
@ensureSpace bytes | ||
|
||
@buffer.write string, @writeIndex, bytes, @encoding | ||
@writeIndex = @writeIndex + bytes | ||
|
||
true | ||
|
||
_readBuffer: (maxBytes = 0) -> | ||
if maxBytes == 0 | ||
@targetIndex = @writeIndex | ||
else | ||
@targetIndex = @readIndex + maxBytes | ||
|
||
if @targetIndex > @writeIndex | ||
@targetIndex = @writeIndex | ||
|
||
buffer = @buffer.slice @readIndex, @targetIndex | ||
@readIndex = @targetIndex | ||
|
||
buffer | ||
|
||
_getLength: () -> | ||
@writeIndex - @readIndex | ||
|
||
|
||
### | ||
# Readable Stream Methods | ||
### | ||
setEncoding: (encoding) -> | ||
if encoding != 'utf8' | ||
throw new Error "Only UTF8 is a supported encoding" | ||
|
||
throw new Error "Not Implemented." | ||
@encoding = encoding | ||
@emitStrings = true | ||
|
||
pause: () -> | ||
@paused = true | ||
|
||
resume: () -> | ||
@paused = false | ||
@flush() | ||
|
||
|
||
_flush: () -> | ||
empty = !@_getLength() | ||
|
||
if @paused or @_destroyed | ||
return | ||
|
||
# Flush some data | ||
@_emitData(@_endWrite or @_destroySoon) | ||
|
||
# Trigger End Event | ||
if empty and @_endWrite | ||
@_emitEnd() | ||
|
||
if empty and @_endWrite and @_destroySoon | ||
@destroy() | ||
|
||
_emitData: (force = false) -> | ||
bytesRemaining = @_getLength() | ||
|
||
if (bytesRemaining >= MIN_BUFFER_SIZE) or force | ||
data = @_readBuffer MAX_BUFFER_SIZE | ||
if data.length | ||
@emit "data", data | ||
|
||
# There may be more data | ||
@flush() | ||
|
||
_emitEnd: () -> | ||
@readable = false | ||
@_endRead = false | ||
@emit "end" | ||
@destroy() | ||
|
||
### | ||
# Writable Stream Methods | ||
### | ||
|
||
write: (data, encoding = 'utf8') -> | ||
if encoding != 'utf8' | ||
throw new Error "Only supports utf8." | ||
|
||
if @_endWrite or @_destroyed | ||
throw new Error "Cannot write to stream, has been ended or destroyed." | ||
|
||
if Buffer.isBuffer data | ||
@_writeBuffer data | ||
else | ||
# String | ||
@_writeString data, encoding | ||
|
||
@flush() | ||
true | ||
|
||
end: (data, encoding) -> | ||
if data? | ||
@write data, encoding | ||
|
||
@writable = false | ||
@_endWrite = true | ||
@flush() | ||
|
||
### | ||
# Readable, Writable Stream Methods | ||
### | ||
flush: () -> | ||
process.nextTick () => | ||
@_flush() | ||
|
||
|
||
destroy: () -> | ||
@_destroyed = true | ||
@writable = false | ||
@readable = false | ||
if !@_endRead | ||
@emit "close" | ||
@cleanup() | ||
|
||
destroySoon: () -> | ||
@end() | ||
@_destroySoon = true | ||
@flush() | ||
|
||
cleanup: () -> | ||
@readIndex = 0 | ||
@writeIndex = 0 | ||
@buffer = null | ||
|
||
module.exports = BufferStream |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
Connect = require 'connect' | ||
|
||
BufferStream = require './bufferstream' | ||
|
||
|
||
|
||
captureResponse = (res, onEndHeader) -> | ||
# Hold on to original functions | ||
write = res.write | ||
end = res.end | ||
writeHead = res.writeHead | ||
setHeader = res.setHeader | ||
|
||
res.reason = "" | ||
res.headers = {} | ||
|
||
# Create paused buffer to collect data | ||
buffer = new BufferStream() | ||
|
||
headersWritten = false | ||
|
||
res.write = (data, encoding) -> | ||
buffer.write data, encoding | ||
|
||
if not headersWritten and onEndHeader | ||
headersWritten = true | ||
onEndHeader res.statusCode, res.reason, res.headers | ||
|
||
res.end = (data, encoding) -> | ||
buffer.end data, encoding | ||
|
||
if not headersWritten and onEndHeader | ||
headersWritten = true | ||
onEndHeader res.statusCode, res.reason, res.headers | ||
|
||
res.writeHead = (_statusCode, _reason..., _headers) -> | ||
statusCode = _statusCode | ||
res.reason = _reason[0] or res.reason | ||
res.headers = _headers or res.headers | ||
|
||
writeHead.apply res, arguments | ||
|
||
if not headersWritten and onEndHeader | ||
headersWritten = true | ||
onEndHeader res.statusCode, res.reason, res.headers | ||
|
||
res.setHeader = (header, value) -> | ||
res.headers[header] = value | ||
|
||
|
||
|
||
newRes = | ||
write: (data, encoding) -> | ||
write.call res, data, encoding | ||
end: (data, encoding) -> | ||
end.call res, data, encoding | ||
on: () -> | ||
res.on.apply res, arguments | ||
emit: () -> | ||
res.emit.apply res, arguments | ||
writable: true | ||
removeListener: () -> | ||
res.removeListener.apply res, arguments | ||
|
||
return [buffer, newRes] | ||
|
||
|
||
module.exports = captureResponse | ||
|
Oops, something went wrong.