github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/api/api.go (about)

     1  package api
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/julienschmidt/httprouter"
     9  )
    10  
    11  // HttpGET is a utility function for making http get requests to sia with a whitelisted user-agent
    12  func HttpGET(url string) (resp *http.Response, err error) {
    13  	req, err := http.NewRequest("GET", url, nil)
    14  	if err != nil {
    15  		return nil, err
    16  	}
    17  	req.Header.Add("User-Agent", "Sia-Agent")
    18  	return new(http.Client).Do(req)
    19  }
    20  
    21  // HttpPOST is a utility function for making post requests to sia with a whitelisted user-agent
    22  func HttpPOST(url string, data string) (resp *http.Response, err error) {
    23  	req, err := http.NewRequest("POST", url, strings.NewReader(data))
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	req.Header.Add("User-Agent", "Sia-Agent")
    28  	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    29  	return new(http.Client).Do(req)
    30  }
    31  
    32  // requireUserAgent is middleware that requires all requests to set a
    33  // UserAgent that contains the specified string.
    34  func requireUserAgent(h http.Handler, ua string) http.Handler {
    35  	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    36  		if !strings.Contains(req.UserAgent(), ua) {
    37  			writeError(w, "Browser access disabled due to security vulnerability. Use Sia-UI or siac.", http.StatusBadRequest)
    38  			return
    39  		}
    40  		h.ServeHTTP(w, req)
    41  	})
    42  }
    43  
    44  // initAPI determines which functions handle each API call.
    45  func (srv *Server) initAPI() {
    46  	router := httprouter.New()
    47  	router.NotFound = http.HandlerFunc(srv.unrecognizedCallHandler) // custom 404
    48  
    49  	// Daemon API Calls
    50  	router.GET("/daemon/constants", srv.daemonConstantsHandler)
    51  	router.GET("/daemon/version", srv.daemonVersionHandler)
    52  	router.GET("/daemon/stop", srv.daemonStopHandler)
    53  
    54  	// Consensus API Calls
    55  	if srv.cs != nil {
    56  		router.GET("/consensus", srv.consensusHandler)
    57  	}
    58  
    59  	// Explorer API Calls
    60  	if srv.explorer != nil {
    61  		router.GET("/explorer", srv.explorerHandler)
    62  		router.GET("/explorer/blocks/:height", srv.explorerBlocksHandler)
    63  		router.GET("/explorer/hashes/:hash", srv.explorerHashHandler)
    64  	}
    65  
    66  	// Gateway API Calls
    67  	if srv.gateway != nil {
    68  		router.GET("/gateway", srv.gatewayHandler)
    69  		router.POST("/gateway/add/:netaddress", srv.gatewayAddHandler)
    70  		router.POST("/gateway/remove/:netaddress", srv.gatewayRemoveHandler)
    71  	}
    72  
    73  	// Host API Calls
    74  	if srv.host != nil {
    75  		// Calls directly pertaining to the host.
    76  		router.GET("/host", srv.hostHandlerGET)                // Get a bunch of information about the host.
    77  		router.POST("/host", srv.hostHandlerPOST)              // Set HostInternalSettings.
    78  		router.POST("/host/announce", srv.hostAnnounceHandler) // Announce the host, optionally on a specific address.
    79  
    80  		// Calls pertaining to the storage manager that the host uses.
    81  		router.GET("/storage", srv.storageHandler)
    82  		router.POST("/storage/folders/add", srv.storageFoldersAddHandler)
    83  		router.POST("/storage/folders/remove", srv.storageFoldersRemoveHandler)
    84  		router.POST("/storage/folders/resize", srv.storageFoldersResizeHandler)
    85  		router.POST("/storage/sectors/delete/:merkleroot", srv.storageSectorsDeleteHandler)
    86  	}
    87  
    88  	// Miner API Calls
    89  	if srv.miner != nil {
    90  		router.GET("/miner", srv.minerHandler)
    91  		router.GET("/miner/header", srv.minerHeaderHandlerGET)
    92  		router.POST("/miner/header", srv.minerHeaderHandlerPOST)
    93  		router.GET("/miner/start", srv.minerStartHandler)
    94  		router.GET("/miner/stop", srv.minerStopHandler)
    95  		router.GET("/miner/headerforwork", srv.minerHeaderHandlerGET)  // COMPATv0.4.8
    96  		router.POST("/miner/submitheader", srv.minerHeaderHandlerPOST) // COMPATv0.4.8
    97  	}
    98  
    99  	// Renter API Calls
   100  	if srv.renter != nil {
   101  		router.GET("/renter", srv.renterHandler)
   102  		router.GET("/renter/allowance", srv.renterAllowanceHandlerGET)
   103  		router.POST("/renter/allowance", srv.renterAllowanceHandlerPOST)
   104  		router.GET("/renter/contracts", srv.renterContractsHandler)
   105  		router.GET("/renter/downloads", srv.renterDownloadsHandler)
   106  		router.GET("/renter/files", srv.renterFilesHandler)
   107  
   108  		router.POST("/renter/load", srv.renterLoadHandler)
   109  		router.POST("/renter/loadascii", srv.renterLoadAsciiHandler)
   110  		router.GET("/renter/share", srv.renterShareHandler)
   111  		router.GET("/renter/shareascii", srv.renterShareAsciiHandler)
   112  
   113  		router.POST("/renter/delete/*siapath", srv.renterDeleteHandler)
   114  		router.GET("/renter/download/*siapath", srv.renterDownloadHandler)
   115  		router.POST("/renter/rename/*siapath", srv.renterRenameHandler)
   116  		router.POST("/renter/upload/*siapath", srv.renterUploadHandler)
   117  
   118  		router.GET("/renter/hosts/active", srv.renterHostsActiveHandler)
   119  		router.GET("/renter/hosts/all", srv.renterHostsAllHandler)
   120  	}
   121  
   122  	// TransactionPool API Calls
   123  	if srv.tpool != nil {
   124  		router.GET("/transactionpool/transactions", srv.transactionpoolTransactionsHandler)
   125  	}
   126  
   127  	// Wallet API Calls
   128  	if srv.wallet != nil {
   129  		router.GET("/wallet", srv.walletHandler)
   130  		router.POST("/wallet/033x", srv.wallet033xHandler)
   131  		router.GET("/wallet/address", srv.walletAddressHandler)
   132  		router.GET("/wallet/addresses", srv.walletAddressesHandler)
   133  		router.GET("/wallet/backup", srv.walletBackupHandler)
   134  		router.POST("/wallet/init", srv.walletInitHandler)
   135  		router.POST("/wallet/lock", srv.walletLockHandler)
   136  		router.POST("/wallet/seed", srv.walletSeedHandler)
   137  		router.GET("/wallet/seeds", srv.walletSeedsHandler)
   138  		router.POST("/wallet/siacoins", srv.walletSiacoinsHandler)
   139  		router.POST("/wallet/siafunds", srv.walletSiafundsHandler)
   140  		router.POST("/wallet/siagkey", srv.walletSiagkeyHandler)
   141  		router.GET("/wallet/transaction/:id", srv.walletTransactionHandler)
   142  		router.GET("/wallet/transactions", srv.walletTransactionsHandler)
   143  		router.GET("/wallet/transactions/:addr", srv.walletTransactionsAddrHandler)
   144  		router.POST("/wallet/unlock", srv.walletUnlockHandler)
   145  		router.POST("/wallet/encrypt", srv.walletInitHandler) // COMPATv0.4.0
   146  	}
   147  
   148  	// Apply UserAgent middleware and create HTTP server
   149  	uaRouter := requireUserAgent(router, srv.requiredUserAgent)
   150  	srv.apiServer = &http.Server{Handler: uaRouter}
   151  }
   152  
   153  // unrecognizedCallHandler handles calls to unknown pages (404).
   154  func (srv *Server) unrecognizedCallHandler(w http.ResponseWriter, req *http.Request) {
   155  	http.Error(w, "404 - Refer to API.md", http.StatusNotFound)
   156  }
   157  
   158  // writeError an error to the API caller.
   159  func writeError(w http.ResponseWriter, msg string, err int) {
   160  	http.Error(w, msg, err)
   161  }
   162  
   163  // writeJSON writes the object to the ResponseWriter. If the encoding fails, an
   164  // error is written instead.
   165  func writeJSON(w http.ResponseWriter, obj interface{}) {
   166  	if json.NewEncoder(w).Encode(obj) != nil {
   167  		http.Error(w, "Failed to encode response", http.StatusInternalServerError)
   168  	}
   169  }
   170  
   171  // writeSuccess writes the success json object ({"Success":true}) to the
   172  // ResponseWriter
   173  func writeSuccess(w http.ResponseWriter) {
   174  	writeJSON(w, struct{ Success bool }{true})
   175  }