Skip to content

Instantly share code, notes, and snippets.

@adam-singer
Forked from mitsuoka/MIME.dart
Created March 4, 2013 02:33
Show Gist options
  • Save adam-singer/5079502 to your computer and use it in GitHub Desktop.
Save adam-singer/5079502 to your computer and use it in GitHub Desktop.
library MIME;
// get MIME type (returns null if there is no such extension)
String mimeType(String extension) => _mimeMaps[extension];
// default MIME type mappings
Map _mimeMaps = const {
'abs': 'audio/x-mpeg',
'ai': 'application/postscript',
'aif': 'audio/x-aiff',
'aifc': 'audio/x-aiff',
'aiff': 'audio/x-aiff',
'aim': 'application/x-aim',
'art': 'image/x-jg',
'asf': 'video/x-ms-asf',
'asx': 'video/x-ms-asf',
'au': 'audio/basic',
'avi': 'video/x-msvideo',
'avx': 'video/x-rad-screenplay',
'bcpio': 'application/x-bcpio',
'bin': 'application/octet-stream',
'bmp': 'image/bmp',
'body': 'text/html',
'cdf': 'application/x-cdf',
'cer': 'application/x-x509-ca-cert',
'class': 'application/java',
'cpio': 'application/x-cpio',
'csh': 'application/x-csh',
'css': 'text/css',
'dart': 'application/vnd.dart',
'dib': 'image/bmp',
'doc': 'application/msword',
'docm': 'application/vnd.ms-word.document.macroEnabled.12',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dot': 'application/msword',
'dotm': 'application/vnd.ms-word.template.macroEnabled.12',
'dotx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'dtd': 'application/xml-dtd',
'dv': 'video/x-dv',
'dvi': 'application/x-dvi',
'eps': 'application/postscript',
'etx': 'text/x-setext',
'exe': 'application/octet-stream',
'gif': 'image/gif',
'gtar': 'application/x-gtar',
'gz': 'application/x-gzip',
'hdf': 'application/x-hdf',
'hqx': 'application/mac-binhex40',
'htc': 'text/x-component',
'htm': 'text/html',
'html': 'text/html',
'ico': 'image/vnd.microsoft.icon',
'ief': 'image/ief',
'jad': 'text/vnd.sun.j2me.app-descriptor',
'jar': 'application/java-archive',
'java': 'text/plain',
'jnlp': 'application/x-java-jnlp-file',
'jpe': 'image/jpeg',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'jsf': 'text/plain',
'jspf': 'text/plain',
'kar': 'audio/x-midi',
'latex': 'application/x-latex',
'm3u': 'audio/x-mpegurl',
'mac': 'image/x-macpaint',
'man': 'application/x-troff-man',
'mathml': 'application/mathml+xml',
'me': 'application/x-troff-me',
'mid': 'audio/x-midi',
'midi': 'audio/x-midi',
'mif': 'application/x-mif',
'mov': 'video/quicktime',
'movie': 'video/x-sgi-movie',
'mp1': 'audio/x-mpeg',
'mp2': 'audio/x-mpeg',
'mp3': 'audio/x-mpeg',
'mp4': 'video/mp4',
'mpa': 'audio/x-mpeg',
'mpe': 'video/mpeg',
'mpeg': 'video/mpeg',
'mpega': 'audio/x-mpeg',
'mpg': 'video/mpeg',
'mpv2': 'video/mpeg2',
'ms': 'application/x-wais-source',
'nc': 'application/x-netcdf',
'oda': 'application/oda',
'odb': 'application/vnd.oasis.opendocument.database',
'odc': 'application/vnd.oasis.opendocument.chart',
'odf': 'application/vnd.oasis.opendocument.formula',
'odg': 'application/vnd.oasis.opendocument.graphics',
'odi': 'application/vnd.oasis.opendocument.image',
'odm': 'application/vnd.oasis.opendocument.text-master',
'odp': 'application/vnd.oasis.opendocument.presentation',
'ods': 'application/vnd.oasis.opendocument.spreadsheet',
'odt': 'application/vnd.oasis.opendocument.text',
'otg': 'application/vnd.oasis.opendocument.graphics-template',
'oth': 'application/vnd.oasis.opendocument.text-web',
'otp': 'application/vnd.oasis.opendocument.presentation-template',
'ots': 'application/vnd.oasis.opendocument.spreadsheet-template',
'ott': 'application/vnd.oasis.opendocument.text-template',
'ogx': 'application/ogg',
'ogv': 'video/ogg',
'oga': 'audio/ogg',
'ogg': 'audio/ogg',
'spx': 'audio/ogg',
'flac': 'audio/flac',
'anx': 'application/annodex',
'axa': 'audio/annodex',
'axv': 'video/annodex',
'xspf': 'application/xspf+xml',
'pbm': 'image/x-portable-bitmap',
'pct': 'image/pict',
'pdf': 'application/pdf',
'pgm': 'image/x-portable-graymap',
'pic': 'image/pict',
'pict': 'image/pict',
'pls': 'audio/x-scpls',
'png': 'image/png',
'pnm': 'image/x-portable-anymap',
'pnt': 'image/x-macpaint',
'ppm': 'image/x-portable-pixmap',
'ppt': 'application/vnd.ms-powerpoint',
'pot': 'application/vnd.ms-powerpoint',
'pps': 'application/vnd.ms-powerpoint',
'ppa': 'application/vnd.ms-powerpoint',
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'potx': 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ppsx': 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'ppam': 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
'pptm': 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
'potm': 'application/vnd.ms-powerpoint.template.macroEnabled.12',
'ppsm': 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
'ps': 'application/postscript',
'psd': 'image/x-photoshop',
'qt': 'video/quicktime',
'qti': 'image/x-quicktime',
'qtif': 'image/x-quicktime',
'ras': 'image/x-cmu-raster',
'rdf': 'application/rdf+xml',
'rgb': 'image/x-rgb',
'rm': 'application/vnd.rn-realmedia',
'roff': 'application/x-troff',
'rtf': 'application/rtf',
'rtx': 'text/richtext',
'sh': 'application/x-sh',
'shar': 'application/x-shar',
// 'shtml': 'text/x-server-parsed-html',
'smf': 'audio/x-midi',
'sit': 'application/x-stuffit',
'snd': 'audio/basic',
'src': 'application/x-wais-source',
'sv4cpio': 'application/x-sv4cpio',
'sv4crc': 'application/x-sv4crc',
'svg': 'image/svg+xml',
'svgz': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
't': 'application/x-troff',
'tar': 'application/x-tar',
'tcl': 'application/x-tcl',
'tex': 'application/x-tex',
'texi': 'application/x-texinfo',
'texinfo': 'application/x-texinfo',
'tif': 'image/tiff',
'tiff': 'image/tiff',
'tr': 'application/x-troff',
'tsv': 'text/tab-separated-values',
'txt': 'text/plain',
'ulw': 'audio/basic',
'ustar': 'application/x-ustar',
'vxml': 'application/voicexml+xml',
'xbm': 'image/x-xbitmap',
'xht': 'application/xhtml+xml',
'xhtml': 'application/xhtml+xml',
'xls': 'application/vnd.ms-excel',
'xlt': 'application/vnd.ms-excel',
'xla': 'application/vnd.ms-excel',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'xlsm': 'application/vnd.ms-excel.sheet.macroEnabled.12',
'xltm': 'application/vnd.ms-excel.template.macroEnabled.12',
'xlam': 'application/vnd.ms-excel.addin.macroEnabled.12',
'xlsb': 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
'xml': 'application/xml',
'xpm': 'image/x-xpixmap',
'xsl': 'application/xml',
'xslt': 'application/xslt+xml',
'xul': 'application/vnd.mozilla.xul+xml',
'xwd': 'image/x-xwindowdump',
'vsd': 'application/x-visio',
'war': 'application/java-archive',
'wav': 'audio/x-wav',
'wbmp': 'image/vnd.wap.wbmp',
'wml': 'text/vnd.wap.wml',
'wmlc': 'application/vnd.wap.wmlc',
'wmls': 'text/vnd.wap.wmlscript',
'wmlscriptc': 'application/vnd.wap.wmlscriptc',
'wmv': 'video/x-ms-wmv',
'wrl': 'x-world/x-vrml',
'wspolicy': 'application/wspolicy+xml',
'Z': 'application/x-compress',
'z': 'application/x-compress',
'zip': 'application/zip'
};
<!--
JavaScript based WebSocketChat client.
This HTML file is used for WebSocketChatServer test.
Open this file from your Chrome browser.
Ref. http://www.websocket.org/echo.html
-->
<!DOCTYPE html>
<meta charset="utf-8" />
<title>WebSocket Chat</title>
<script language="javascript" type="text/javascript">
var wsUri = "ws://localhost:8000/chat";
var mode = "DISCONNECTED";
window.addEventListener("load", init, false);
function init() {
var consoleLog = document.getElementById("consoleLog");
var clearLogBut = document.getElementById("clearLogButton");
clearLogBut.onclick = clearLog;
var connectBut = document.getElementById("joinButton");
connectBut.onclick = doConnect;
var disconnectBut = document.getElementById("leaveButton");
disconnectBut.onclick = doDisconnect;
var sendBut = document.getElementById("sendButton");
sendBut.onclick = doSend;
var userName = document.getElementById("userName");
var sendMessage = document.getElementById("sendMessage");
}
function onOpen(evt) {
logToConsole("CONNECTED");
mode = "CONNECTED";
websocket.send("userName=" + userName.value);
}
function onClose(evt) {
logToConsole("DISCONNECTED");
mode = "DISCONNECTED";
}
function onMessage(evt) {
logToConsole('<span style="color: blue;">' + evt.data+'</span>');
}
function onError(evt) {
logToConsole('<span style="color: red;">ERROR:</span> ' + evt.data);
websocket.close();
}
function doConnect() {
if (mode == "CONNECTED") {
return;
}
if (window.MozWebSocket) {
logToConsole('<span style="color: red;"><strong>Info:</strong> This browser supports WebSocket using the MozWebSocket constructor</span>');
window.WebSocket = window.MozWebSocket;
}
else if (!window.WebSocket) {
logToConsole('<span style="color: red;"><strong>Error:</strong> This browser does not have support for WebSocket</span>');
return;
}
if (!userName.value) {
logToConsole('<span style="color: red;"><strong>Enter your name!</strong></span>');
return;
}
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function doDisconnect() {
if (mode == "CONNECTED") {
}
websocket.close();
}
function doSend() {
if (sendMessage.value != "" && mode == "CONNECTED") {
websocket.send(sendMessage.value);
sendMessage.value = "";
}
}
function clearLog() {
while (consoleLog.childNodes.length > 0) {
consoleLog.removeChild(consoleLog.lastChild);
}
}
function logToConsole(message) {
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
consoleLog.appendChild(pre);
while (consoleLog.childNodes.length > 50) {
consoleLog.removeChild(consoleLog.firstChild);
}
consoleLog.scrollTop = consoleLog.scrollHeight;
}
</script>
<h2>WebSocket Chat Sample</h2>
<div id="chat">
<div id="chat-access">
<strong>Your Name:</strong><br>
<input id="userName" cols="40">
<br>
<button id="joinButton">Join</button>
<button id="leaveButton">Leave</button>
<br>
<br>
<strong>Message:</strong><br>
<textarea rows="5" id="sendMessage" style="font-size:small; width:250px"></textarea>
<br>
<button id="sendButton">Send</button>
<br>
<br>
</div>
<div id="chat-log"> <strong>Chat:</strong>
<div id="consoleLog" style="font-size:small; width:270px; border:solid;
border-width:1px; height:172px; overflow-y:scroll"></div>
<button id="clearLogButton" style="position: relative; top: 3px;">Clear log</button>
</div>
</div>
</html>
/*
Dart code sample : WebSocket chat client for Dartium
1. Save these files and dart.js into a folder named WebSocketChat.
2. From Dart editor, File > Open Folder and select this WebSocketChat folder.
3. Run WebSocketChatServer.dart as server.
4. Call the the server from Dartium: http://localhost:8080/chat
5. To establish WebSocket connection, enter your name and click 'join' button.
6. To chat, enter chat message and click 'send' button.
7. To close the connection, click 'leave' button
June 2012, by Cresc Corp.
February 2013, revised to incorporate re-designed dart:html library.
Ref: www.cresc.co.jp/tech/java/Google_Dart/DartLanguageGuide.pdf (in Japanese)
*/
import 'dart:html';
var wsUri = 'ws://localhost:8000/chat';
var mode = 'DISCONNECTED';
WebSocket webSocket;
var userName;
var sendMessage;
var consoleLog;
void main() {
show('Dart WebSocket Chat Sample');
userName = document.query('#userName');
sendMessage = document.query('#sendMessage');
consoleLog = document.query('#consoleLog');
document.query('#clearLogButton').onClick.listen((e) {clearLog();});
document.query('#joinButton').onClick.listen((e) {doConnect();});
document.query('#leaveButton').onClick.listen((e) {doDisconnect();});
document.query('#sendButton').onClick.listen((e) {doSend();});
}
doConnect() {
if (mode == 'CONNECTED') {
return;
}
if (userName.value == '') {
logToConsole('<span style="color: red;"><strong>Enter your name!</strong></span>');
return;
}
webSocket = new WebSocket(wsUri);
webSocket.onOpen.listen(onOpen);
webSocket.onClose.listen(onClose);
webSocket.onMessage.listen(onMessage);
webSocket.onError.listen(onError);
}
doDisconnect() {
if (mode == 'CONNECTED') {
}
webSocket.close();
}
doSend() {
if (sendMessage.value != '' && mode == 'CONNECTED') {
webSocket.send(sendMessage.value);
sendMessage.value = '';
}
}
clearLog() {
while (consoleLog.nodes.length > 0) {
consoleLog.nodes.removeLast();
}
}
onOpen(open) {
logToConsole('CONNECTED');
mode = 'CONNECTED';
webSocket.send('userName=${userName.value}');
}
onClose(close) {
logToConsole('DISCONNECTED');
mode = 'DISCONNECTED';
}
onMessage(message) {
logToConsole('<span style="color: blue;">${message.data}</span>');
}
onError(error) {
logToConsole('<span style="color: red;">ERROR:</span> ${error}');
webSocket.close();
}
logToConsole(message) {
Element pre = new Element.tag('p');
pre.style.wordWrap = 'break-word';
pre.innerHtml = message;
consoleLog.nodes.add(pre);
while (consoleLog.nodes.length > 50) {
consoleLog.$dom_removeChild(consoleLog.nodes[0]);
}
pre.scrollIntoView();
}
show(String message) {
document.query('#status').text = message;
}
<!--
Dart based WebSocketChat client
Open this file from Dartium browser
-->
<!DOCTYPE html>
<meta charset="utf-8" />
<head>
<title>WebSocketChatClient</title>
</head>
<body>
<h1>WebSocketChatClient</h1>
<h2 id="status">dart is not running</h2>
<script type="application/dart" src="chat/WebSocketChatClient.dart"></script>
<script src="/chat/dart.js"></script>
<div id="chat">
<div id="chat-access">
<strong>Your Name:</strong><br>
<input id="userName" cols="40">
<br>
<button id="joinButton">Join</button>
<button id="leaveButton">Leave</button>
<br>
<br>
<strong>Message:</strong><br>
<textarea rows="5" id="sendMessage" style="font-size:small; width:250px"></textarea>
<br>
<button id="sendButton">Send</button>
<br>
<br>
</div>
<div id="chat-log"> <strong>Chat:</strong>
<div id="consoleLog" style="font-size:small; width:270px; border:solid;
border-width:1px; height:172px; overflow-y:scroll"></div>
<button id="clearLogButton" style="position: relative; top: 3px;">Clear log</button>
</div>
</div>
<body>
</html>
/*
Dart code sample : WebSocket chat server
1. Save these files and dart.js into a folder named WebSocketChat.
2. From Dart editor, File > Open Folder and select this WebSocketChat folder.
3. Run this WebSocketChatServer.dart as server.
4. Access the server from Dartium or Chrome browser:
http://localhost:8080/chat
This chat server will distinguish Dartium and returns Dart based client page.
For the request from Chrome, this server returns JS based client page.
5. To establish the WebSocket connection, enter your name and click 'join' button.
6. To chat, enter chat message and click 'send' button.
7. To close the connection, click 'leave' button
Source : http://blog.sethladd.com/2012/04/dart-server-supports-web-sockets.html
June 2012, modified by Cresc Corp.
Sept. 2012, modified to incorpolate catch syntax change
Oct. 2012, incorporated M1 changes
Feb. 2013, incorporated re-designed dart:io library
Ref: www.cresc.co.jp/tech/java/Google_Dart/DartLanguageGuide.pdf (in Japanese)
*/
import 'dart:io';
import 'dart:async';
import 'MIME.dart' as mime;
final HOST = "127.0.0.1";
final WS_PORT = 8000;
final HTTP_PORT = 8080;
final LOG_REQUESTS = false;
Map<String, WebSocket> users = {}; // Map of current users
void main() {
users = new Map<String, WebSocket>();
WebSocketHandler webSocketHandler = new WebSocketHandler();
HttpRequestHandler httpRequestHandler = new HttpRequestHandler();
HttpServer.bind(HOST, WS_PORT)
.then((HttpServer server) {
server
.where((request) => request.uri.path == '/chat')
.transform(new WebSocketTransformer())
.listen((WebSocket ws){
webSocketHandler.wsHandler(ws);
});
});
print('Serving chat on : ${HOST}:${WS_PORT}.');
HttpServer.bind(HOST, HTTP_PORT)
.then((HttpServer server) {
server
.where((request) => request.uri.path.startsWith('/chat'))
.listen((HttpRequest request) {
httpRequestHandler.requestHandler(request);
});
});
print('Serving ChatPage request on : ${HOST}:${HTTP_PORT}.');
}
// handle WebSocket events
class WebSocketHandler {
wsHandler(WebSocket ws) {
if (LOG_REQUESTS) {
log('${new DateTime.now().toString()} - New connection ${ws.hashCode} '
'(active connections : ${users.length+1})');
}
ws.listen((event) {
if (event is MessageEvent) {
processMessage(ws, event);
} else if (event is CloseEvent) {
processClosed(ws, event);
if(LOG_REQUESTS){
print('${new DateTime.now().toString()} - connection ${ws.hashCode} '
'closed with ${event.code} for ${event.reason}');
}
}
});
}
processMessage(WebSocket ws, MessageEvent event) {
try {
String receivedMessage = event.data;
var sendMessage, userName;
userName = getUserName(ws);
if (LOG_REQUESTS) {
log('${new DateTime.now().toString()} - Received message on connection'
' ${ws.hashCode}: $receivedMessage');
}
if (userName != null) { sendMessage = '${timeStamp()} $userName >> $receivedMessage';
} else if (receivedMessage.startsWith("userName=")) {
userName = receivedMessage.substring(9);
if (users[userName] != null) {
ws.send('ERROR - This name is already being used!');
if (LOG_REQUESTS) {
log('${new DateTime.now().toString()} - Illegal name, closed '
'connection ${ws.hashCode} (active connections : ${users.length})');
}
ws.close();
return;
}
else { users['$userName'] = ws;
}
sendMessage = '${timeStamp()} * $userName joined.';
}
sendAll(sendMessage);
} on Exception catch (err) {
log('${timeStamp()} Exception - ${err.toString()}');
}
}
processClosed(WebSocket ws, CloseEvent event){
try {
if (LOG_REQUESTS) {
log('${new DateTime.now().toString()} - Closed connection '
'${ws.hashCode} with ${event.code} for ${event.reason}'
'(active connections : ${users.length-1})');
}
String userName = getUserName(ws);
if (userName != null) {
String sendMessage = '${timeStamp()} * $userName left.';
users.remove(userName);
sendAll(sendMessage);
}
} on Exception catch (err) {
log('${new DateTime.now().toString()} Exception - ${err.toString()}');
}
}
String getUserName(WebSocket ws) {
String userName;
users.forEach((key, value) {
if (value == ws) userName = key;
});
return userName;
}
void sendAll(String sendMessage) {
users.forEach((key, value) {
value.send(preFormat(sendMessage));
});
}
}
String timeStamp() => new DateTime.now().toString().substring(11,16);
String preFormat(String s) {
StringBuffer b = new StringBuffer();
String c;
bool nbsp = false;
for (int i = 0; i < s.length; i++){
c = s[i];
if (c != ' ') nbsp = false;
if (c == '&') { b.write('&amp;');
} else if (c == '"') { b.write('&quot;');
} else if (c == "'") { b.write('&#39;');
} else if (c == '<') { b.write('&lt;');
} else if (c == '>') { b.write('&gt;');
} else if (c == '\n') { b.write('<br>');
} else if (c == ' ') {
if (!nbsp) {
b.write(' ');
nbsp = true;
}
else { b.write('&nbsp;');
}
}
else { b.write(c);
}
}
return b.toString();
}
// adapt this function to your logger
void log(String s) {
print(s);
}
// handle HTTP requests
class HttpRequestHandler {
void requestHandler(HttpRequest request) {
HttpResponse response = request.response;
try {
String fileName = request.uri.path;
if (fileName == '/chat') {
if (request.headers['user-agent'][0].contains('Dart')) {
fileName = 'WebSocketChatClient.html';
}
else { fileName = 'WebSocketChat.html';
}
new FileHandler().onRequest(request, response, fileName);
}
else if (fileName.startsWith('/chat/')){
fileName = request.uri.path.replaceFirst('/chat/', '');
new FileHandler().onRequest(request, response, fileName);
}
else { new NotFoundHandler().onRequest(request, response);
}
}
on Exception catch (err) {
print('Http request handler error : $err.toString()');
}
}
}
class FileHandler {
FileHandler(){
}
void onRequest(HttpRequest request, HttpResponse response, String fileName) {
try {
if (LOG_REQUESTS) {
print('Requested file name : $fileName');
}
File file = new File(fileName);
if (file.existsSync()) {
String mimeType = 'text/html; charset=UTF-8';
int lastDot = fileName.lastIndexOf('.', fileName.length - 1);
if (lastDot != -1) {
String extension = fileName.substring(lastDot + 1);
mimeType = mime.mimeType(extension);
}
response.headers.set('Content-Type', mimeType);
RandomAccessFile openedFile = file.openSync();
response.contentLength = openedFile.lengthSync();
openedFile.closeSync();
// Pipe the file content into the response.
file.openRead().pipe(response);
} else {
if (LOG_REQUESTS) {
print('File not found: $fileName');
}
new NotFoundHandler().onRequest(request, response);
}
} on Exception catch (err) {
print('File handler error : $err.toString()');
}
}
}
class NotFoundHandler {
NotFoundHandler(){
}
List<int> _notFoundPage;
static final String notFoundPageHtml = '''
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL or File was not found on this server.</p>
</body></html>''';
void onRequest(HttpRequest request, HttpResponse response){
if (_notFoundPage == null) {
_notFoundPage = notFoundPageHtml.charCodes;
}
response.statusCode = HttpStatus.NOT_FOUND;
response.headers.set('Content-Type', 'text/html; charset=UTF-8');
response.contentLength = _notFoundPage.length;
response.add(_notFoundPage);
response.close();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment