mirror of
https://github.com/zhigang1992/mitmproxy.git
synced 2026-04-23 20:00:09 +08:00
Merge remote-tracking branch 'jason/websocket'
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,16 +1,15 @@
|
||||
import React from "react"
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import { applyMiddleware, createStore } from 'redux'
|
||||
import { Provider } from 'react-redux'
|
||||
import createLogger from 'redux-logger'
|
||||
import thunkMiddleware from 'redux-thunk'
|
||||
import { Route, Router as ReactRouter, hashHistory, Redirect } from "react-router"
|
||||
import { Route, Router as ReactRouter, hashHistory, Redirect } from 'react-router'
|
||||
|
||||
import Connection from "./connection"
|
||||
import ProxyApp from "./components/ProxyApp"
|
||||
import ProxyApp from './components/ProxyApp'
|
||||
import MainView from './components/MainView'
|
||||
import rootReducer from './ducks/index'
|
||||
import { addLogEntry } from "./ducks/eventLog"
|
||||
import { addLogEntry } from './ducks/eventLog'
|
||||
|
||||
// logger must be last
|
||||
const store = createStore(
|
||||
@@ -18,14 +17,13 @@ const store = createStore(
|
||||
applyMiddleware(thunkMiddleware, createLogger())
|
||||
)
|
||||
|
||||
// @todo move to ProxyApp
|
||||
window.addEventListener('error', msg => {
|
||||
store.dispatch(addLogEntry(msg))
|
||||
})
|
||||
|
||||
// @todo remove this
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.ws = new Connection("/updates", store.dispatch)
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<ReactRouter history={hashHistory}>
|
||||
|
||||
@@ -3,6 +3,7 @@ import ReactDOM from 'react-dom'
|
||||
import _ from 'lodash'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import { init as appInit, destruct as appDestruct } from '../ducks/app'
|
||||
import Header from './Header'
|
||||
import EventLog from './EventLog'
|
||||
import Footer from './Footer'
|
||||
@@ -26,27 +27,8 @@ class ProxyAppMain extends Component {
|
||||
this.updateLocation = this.updateLocation.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo move to actions
|
||||
*/
|
||||
updateLocation(pathname, queryUpdate) {
|
||||
if (pathname === undefined) {
|
||||
pathname = this.props.location.pathname
|
||||
}
|
||||
const query = this.props.location.query
|
||||
for (const key of Object.keys(queryUpdate || {})) {
|
||||
query[key] = queryUpdate[key] || undefined
|
||||
}
|
||||
this.context.router.replace({ pathname, query })
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo pass in with props
|
||||
*/
|
||||
getQuery() {
|
||||
// For whatever reason, react-router always returns the same object, which makes comparing
|
||||
// the current props with nextProps impossible. As a workaround, we just clone the query object.
|
||||
return _.clone(this.props.location.query)
|
||||
componentWillMount() {
|
||||
this.props.appInit()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,6 +38,10 @@ class ProxyAppMain extends Component {
|
||||
this.focus()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.appDestruct()
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo use props
|
||||
*/
|
||||
@@ -110,6 +96,29 @@ class ProxyAppMain extends Component {
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo move to actions
|
||||
*/
|
||||
updateLocation(pathname, queryUpdate) {
|
||||
if (pathname === undefined) {
|
||||
pathname = this.props.location.pathname
|
||||
}
|
||||
const query = this.props.location.query
|
||||
for (const key of Object.keys(queryUpdate || {})) {
|
||||
query[key] = queryUpdate[key] || undefined
|
||||
}
|
||||
this.context.router.replace({ pathname, query })
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo pass in with props
|
||||
*/
|
||||
getQuery() {
|
||||
// For whatever reason, react-router always returns the same object, which makes comparing
|
||||
// the current props with nextProps impossible. As a workaround, we just clone the query object.
|
||||
return _.clone(this.props.location.query)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { showEventLog, location, children } = this.props
|
||||
const query = this.getQuery()
|
||||
@@ -132,5 +141,10 @@ class ProxyAppMain extends Component {
|
||||
export default connect(
|
||||
state => ({
|
||||
showEventLog: state.eventLog.visible,
|
||||
})
|
||||
settings: state.settings.settings,
|
||||
}),
|
||||
{
|
||||
appInit,
|
||||
appDestruct,
|
||||
}
|
||||
)(ProxyAppMain)
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import {ConnectionActions} from "./actions.js";
|
||||
import {AppDispatcher} from "./dispatcher.js";
|
||||
import * as webSocketActions from "./ducks/websocket"
|
||||
import * as eventLogActions from "./ducks/eventLog"
|
||||
import * as flowActions from "./ducks/flows"
|
||||
import * as settingsActions from './ducks/settings'
|
||||
|
||||
export default function Connection(url, dispatch) {
|
||||
if (url[0] === "/") {
|
||||
url = location.origin.replace("http", "ws") + url;
|
||||
}
|
||||
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = function () {
|
||||
dispatch(webSocketActions.connected())
|
||||
dispatch(settingsActions.fetchSettings())
|
||||
dispatch(flowActions.fetchFlows())
|
||||
// workaround to make sure that our state is already available.
|
||||
.then(() => {
|
||||
console.log("flows are loaded now")
|
||||
ConnectionActions.open()
|
||||
})
|
||||
dispatch(eventLogActions.fetchLogEntries())
|
||||
};
|
||||
ws.onmessage = function (m) {
|
||||
var message = JSON.parse(m.data);
|
||||
AppDispatcher.dispatchServerAction(message);
|
||||
switch (message.type) {
|
||||
case eventLogActions.UPDATE_LOG:
|
||||
return dispatch(eventLogActions.updateLogEntries(message))
|
||||
case flowActions.UPDATE_FLOWS:
|
||||
return dispatch(flowActions.updateFlows(message))
|
||||
case settingsActions.UPDATE_SETTINGS:
|
||||
return dispatch(settingsActions.handleWsMsg(message))
|
||||
default:
|
||||
console.warn("unknown message", message)
|
||||
}
|
||||
};
|
||||
ws.onerror = function () {
|
||||
ConnectionActions.error();
|
||||
dispatch(eventLogActions.addLogEntry("WebSocket connection error."));
|
||||
};
|
||||
ws.onclose = function () {
|
||||
ConnectionActions.close();
|
||||
dispatch(eventLogActions.addLogEntry("WebSocket connection closed."));
|
||||
dispatch(webSocketActions.disconnected());
|
||||
};
|
||||
return ws;
|
||||
}
|
||||
27
web/src/js/ducks/app.js
Normal file
27
web/src/js/ducks/app.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { connect as wsConnect, disconnect as wsDisconnect } from './websocket'
|
||||
|
||||
export const INIT = 'APP_INIT'
|
||||
|
||||
const defaultState = {}
|
||||
|
||||
export function reduce(state = defaultState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export function init() {
|
||||
return dispatch => {
|
||||
dispatch(wsConnect())
|
||||
dispatch({ type: INIT })
|
||||
}
|
||||
}
|
||||
|
||||
export function destruct() {
|
||||
return dispatch => {
|
||||
dispatch(wsDisconnect())
|
||||
dispatch({ type: DESTRUCT })
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,113 @@
|
||||
const CONNECTED = 'WEBSOCKET_CONNECTED'
|
||||
const DISCONNECTED = 'WEBSOCKET_DISCONNECTED'
|
||||
import { ConnectionActions } from '../actions.js'
|
||||
import { AppDispatcher } from '../dispatcher.js'
|
||||
import * as eventLogActions from './eventLog'
|
||||
import * as flowsActions from './flows'
|
||||
import * as settingsActions from './settings'
|
||||
|
||||
export const SYM_SOCKET = Symbol('WEBSOCKET_SYM_SOCKET')
|
||||
|
||||
const defaultState = {
|
||||
connected: false,
|
||||
/* we may want to have an error message attribute here at some point */
|
||||
}
|
||||
export default function reducer(state = defaultState, action) {
|
||||
export const CONNECT = 'WEBSOCKET_CONNECT'
|
||||
export const CONNECTED = 'WEBSOCKET_CONNECTED'
|
||||
export const DISCONNECT = 'WEBSOCKET_DISCONNECT'
|
||||
export const DISCONNECTED = 'WEBSOCKET_DISCONNECTED'
|
||||
export const ERROR = 'WEBSOCKET_ERROR'
|
||||
export const MESSAGE = 'WEBSOCKET_MESSAGE'
|
||||
|
||||
/* we may want to have an error message attribute here at some point */
|
||||
const defaultState = { connected: false, socket: null }
|
||||
|
||||
export default function reduce(state = defaultState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case CONNECT:
|
||||
return { ...state, [SYM_SOCKET]: action.socket }
|
||||
|
||||
case CONNECTED:
|
||||
return {
|
||||
connected: true
|
||||
}
|
||||
return { ...state, connected: true }
|
||||
|
||||
case DISCONNECT:
|
||||
return { ...state, connected: false }
|
||||
|
||||
case DISCONNECTED:
|
||||
return {
|
||||
connected: false
|
||||
}
|
||||
return { ...state, [SYM_SOCKET]: null, connected: false }
|
||||
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export function connect() {
|
||||
return dispatch => {
|
||||
const socket = new WebSocket(location.origin.replace('http', 'ws') + '/updates')
|
||||
|
||||
export function connected() {
|
||||
return {type: CONNECTED}
|
||||
// @todo remove this
|
||||
window.ws = socket
|
||||
|
||||
socket.addEventListener('open', () => dispatch(onConnect()))
|
||||
socket.addEventListener('close', () => dispatch(onDisconnect()))
|
||||
socket.addEventListener('message', msg => dispatch(onMessage(msg)))
|
||||
socket.addEventListener('error', error => dispatch(onError(error)))
|
||||
|
||||
dispatch({ type: CONNECT, socket })
|
||||
|
||||
return socket
|
||||
}
|
||||
}
|
||||
export function disconnected() {
|
||||
return {type: DISCONNECTED}
|
||||
|
||||
export function disconnect() {
|
||||
return (dispatch, getState) => {
|
||||
getState().settings[SYM_SOCKET].close()
|
||||
dispatch({ type: DISCONNECT })
|
||||
}
|
||||
}
|
||||
|
||||
export function onConnect() {
|
||||
// workaround to make sure that our state is already available.
|
||||
return dispatch => {
|
||||
dispatch({ type: CONNECTED })
|
||||
dispatch(settingsActions.fetchSettings())
|
||||
dispatch(flowsActions.fetchFlows()).then(() => ConnectionActions.open())
|
||||
}
|
||||
}
|
||||
|
||||
export function onMessage(msg) {
|
||||
return dispatch => {
|
||||
const data = JSON.parse(msg.data)
|
||||
|
||||
AppDispatcher.dispatchServerAction(data)
|
||||
|
||||
switch (data.type) {
|
||||
|
||||
case eventLogActions.UPDATE_LOG:
|
||||
return dispatch(eventLogActions.updateLogEntries(data))
|
||||
|
||||
case flowsActions.UPDATE_FLOWS:
|
||||
return dispatch(flowsActions.updateFlows(data))
|
||||
|
||||
case settingsActions.UPDATE_SETTINGS:
|
||||
return dispatch(settingsActions.updateSettings(message))
|
||||
|
||||
default:
|
||||
console.warn('unknown message', data)
|
||||
}
|
||||
|
||||
dispatch({ type: MESSAGE, msg })
|
||||
}
|
||||
}
|
||||
|
||||
export function onDisconnect() {
|
||||
return dispatch => {
|
||||
ConnectionActions.close()
|
||||
dispatch(eventLogActions.addLogEntry('WebSocket connection closed.'))
|
||||
dispatch({ type: DISCONNECTED })
|
||||
}
|
||||
}
|
||||
|
||||
export function onError(error) {
|
||||
// @todo let event log subscribe WebSocketActions.ERROR
|
||||
return dispatch => {
|
||||
ConnectionActions.error()
|
||||
dispatch(eventLogActions.addLogEntry('WebSocket connection error.'))
|
||||
dispatch({ type: ERROR, error })
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user