2017-05-26 08:57:09 +01:00
// Copyright 2017 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package routing
import (
"net/http"
2020-06-16 18:31:38 +01:00
"strings"
2017-05-26 08:57:09 +01:00
2020-06-16 14:10:55 +01:00
userapi "github.com/matrix-org/dendrite/userapi/api"
2017-09-28 14:50:40 +01:00
2017-05-26 08:57:09 +01:00
"github.com/gorilla/mux"
2020-05-21 14:40:13 +01:00
"github.com/matrix-org/dendrite/internal/config"
2020-06-12 14:55:57 +01:00
"github.com/matrix-org/dendrite/internal/httputil"
2017-05-26 15:49:54 +01:00
"github.com/matrix-org/dendrite/mediaapi/storage"
2017-05-26 08:57:09 +01:00
"github.com/matrix-org/dendrite/mediaapi/types"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus"
2019-12-17 16:47:45 +00:00
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
2017-05-26 08:57:09 +01:00
)
2020-05-22 11:43:17 +01:00
const pathPrefixR0 = "/media/r0"
2020-06-16 14:29:11 +01:00
const pathPrefixV1 = "/media/v1" // TODO: remove when synapse is fixed
2017-05-26 08:57:09 +01:00
2017-08-03 15:10:39 +01:00
// Setup registers the media API HTTP handlers
2019-07-03 16:38:50 +01:00
//
// Due to Setup being used to call many other functions, a gocyclo nolint is
// applied:
// nolint: gocyclo
2017-09-21 16:20:10 +01:00
func Setup (
2020-05-22 11:43:17 +01:00
publicAPIMux * mux . Router ,
2020-08-10 14:18:04 +01:00
cfg * config . MediaAPI ,
2020-01-03 14:07:05 +00:00
db storage . Database ,
2020-06-16 14:10:55 +01:00
userAPI userapi . UserInternalAPI ,
2017-09-21 16:20:10 +01:00
client * gomatrixserverlib . Client ,
) {
2020-05-22 11:43:17 +01:00
r0mux := publicAPIMux . PathPrefix ( pathPrefixR0 ) . Subrouter ( )
2020-06-16 14:29:11 +01:00
v1mux := publicAPIMux . PathPrefix ( pathPrefixV1 ) . Subrouter ( )
2017-06-07 00:12:49 +01:00
activeThumbnailGeneration := & types . ActiveThumbnailGeneration {
PathToResult : map [ string ] * types . ThumbnailGenerationResult { } ,
}
2020-07-08 16:39:50 +01:00
uploadHandler := httputil . MakeAuthAPI (
2020-06-16 14:10:55 +01:00
"upload" , userAPI ,
func ( req * http . Request , _ * userapi . Device ) util . JSONResponse {
2017-10-11 18:16:53 +01:00
return Upload ( req , cfg , db , activeThumbnailGeneration )
2017-09-28 14:50:40 +01:00
} ,
2020-07-08 16:39:50 +01:00
)
r0mux . Handle ( "/upload" , uploadHandler ) . Methods ( http . MethodPost , http . MethodOptions )
v1mux . Handle ( "/upload" , uploadHandler ) . Methods ( http . MethodPost , http . MethodOptions )
2017-05-26 08:57:09 +01:00
activeRemoteRequests := & types . ActiveRemoteRequests {
2017-05-31 16:56:11 +01:00
MXCToResult : map [ string ] * types . RemoteRequestResult { } ,
2017-05-26 08:57:09 +01:00
}
2020-06-16 14:29:11 +01:00
downloadHandler := makeDownloadAPI ( "download" , cfg , db , client , activeRemoteRequests , activeThumbnailGeneration )
r0mux . Handle ( "/download/{serverName}/{mediaId}" , downloadHandler ) . Methods ( http . MethodGet , http . MethodOptions )
2020-06-17 11:53:26 +01:00
r0mux . Handle ( "/download/{serverName}/{mediaId}/{downloadName}" , downloadHandler ) . Methods ( http . MethodGet , http . MethodOptions )
v1mux . Handle ( "/download/{serverName}/{mediaId}" , downloadHandler ) . Methods ( http . MethodGet , http . MethodOptions ) // TODO: remove when synapse is fixed
v1mux . Handle ( "/download/{serverName}/{mediaId}/{downloadName}" , downloadHandler ) . Methods ( http . MethodGet , http . MethodOptions ) // TODO: remove when synapse is fixed
2020-06-16 14:29:11 +01:00
2017-06-07 00:12:49 +01:00
r0mux . Handle ( "/thumbnail/{serverName}/{mediaId}" ,
2017-09-21 16:20:10 +01:00
makeDownloadAPI ( "thumbnail" , cfg , db , client , activeRemoteRequests , activeThumbnailGeneration ) ,
2018-03-13 15:55:45 +00:00
) . Methods ( http . MethodGet , http . MethodOptions )
2017-05-26 08:57:09 +01:00
}
2017-06-07 00:12:49 +01:00
2017-09-21 16:20:10 +01:00
func makeDownloadAPI (
name string ,
2020-08-10 14:18:04 +01:00
cfg * config . MediaAPI ,
2020-01-03 14:07:05 +00:00
db storage . Database ,
2017-09-21 16:20:10 +01:00
client * gomatrixserverlib . Client ,
activeRemoteRequests * types . ActiveRemoteRequests ,
activeThumbnailGeneration * types . ActiveThumbnailGeneration ,
) http . HandlerFunc {
2019-12-18 15:10:53 +00:00
counterVec := promauto . NewCounterVec (
prometheus . CounterOpts {
Name : name ,
Help : "Total number of media_api requests for either thumbnails or full downloads" ,
2019-12-17 16:47:45 +00:00
} ,
2019-12-18 15:10:53 +00:00
[ ] string { "code" } ,
)
httpHandler := func ( w http . ResponseWriter , req * http . Request ) {
req = util . RequestWithLogging ( req )
2020-05-21 14:40:13 +01:00
// Set internal headers returned regardless of the outcome of the request
2019-12-18 15:10:53 +00:00
util . SetCORSHeaders ( w )
// Content-Type will be overridden in case of returning file data, else we respond with JSON-formatted errors
w . Header ( ) . Set ( "Content-Type" , "application/json" )
2020-06-16 18:31:38 +01:00
2020-06-12 14:55:57 +01:00
vars , _ := httputil . URLDecodeMapValues ( mux . Vars ( req ) )
2020-06-16 18:31:38 +01:00
serverName := gomatrixserverlib . ServerName ( vars [ "serverName" ] )
// For the purposes of loop avoidance, we will return a 404 if allow_remote is set to
// false in the query string and the target server name isn't our own.
// https://github.com/matrix-org/matrix-doc/pull/1265
if allowRemote := req . URL . Query ( ) . Get ( "allow_remote" ) ; strings . ToLower ( allowRemote ) == "false" {
if serverName != cfg . Matrix . ServerName {
w . WriteHeader ( http . StatusNotFound )
return
}
}
2019-12-18 15:10:53 +00:00
Download (
w ,
req ,
2020-06-16 18:31:38 +01:00
serverName ,
2019-12-18 15:10:53 +00:00
types . MediaID ( vars [ "mediaId" ] ) ,
cfg ,
db ,
client ,
activeRemoteRequests ,
activeThumbnailGeneration ,
name == "thumbnail" ,
2020-06-17 11:53:26 +01:00
vars [ "downloadName" ] ,
2019-12-18 15:10:53 +00:00
)
}
return promhttp . InstrumentHandlerCounter ( counterVec , http . HandlerFunc ( httpHandler ) )
2017-06-07 00:12:49 +01:00
}