func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCallback func(gomatrixserverlib.EDU)) func(*Server) {
	return func(srv *Server) {
		srv.mux.Handle("/_matrix/federation/v1/send/{transactionID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			// Extract the transaction ID from the request vars
			vars := mux.Vars(req)
			transactionID := vars["transactionID"]

			// Check federation signature
			fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
				req, time.Now(), gomatrixserverlib.ServerName(srv.ServerName), srv.keyRing,
			)
			if fedReq == nil {
				log.Printf(
					"complement: Transaction '%s': HTTP Code %d. Invalid http request: %s",
					transactionID, errResp.Code, errResp.JSON,
				)

				w.WriteHeader(errResp.Code)
				b, _ := json.Marshal(errResp.JSON)
				w.Write(b)
				return
			}

			// Unmarshal the request body into a transaction object
			var transaction gomatrixserverlib.Transaction
			err := json.Unmarshal(fedReq.Content(), &transaction)
			if err != nil {
				log.Printf(
					"complement: Transaction '%s': Unable to unmarshal transaction body bytes into Transaction object: %s",
					transaction.TransactionID, err.Error(),
				)

				errResp := util.MessageResponse(400, err.Error())
				w.WriteHeader(errResp.Code)
				b, _ := json.Marshal(errResp.JSON)
				w.Write(b)
				return
			}
			transaction.TransactionID = gomatrixserverlib.TransactionID(transactionID)

			// Transactions are limited in size; they can have at most 50 PDUs and 100 EDUs.
			// https://matrix.org/docs/spec/server_server/latest#transactions
			if len(transaction.PDUs) > 50 || len(transaction.EDUs) > 100 {
				log.Printf(
					"complement: Transaction '%s': Transaction too large. PDUs: %d/50, EDUs: %d/100",
					transaction.TransactionID, len(transaction.PDUs), len(transaction.EDUs),
				)

				errResp := util.MessageResponse(400, "Transactions are limited to 50 PDUs and 100 EDUs")
				w.WriteHeader(errResp.Code)
				b, _ := json.Marshal(errResp.JSON)
				w.Write(b)
				return
			}

			// Construct a response and fill as we process each PDU
			response := gomatrixserverlib.RespSend{}
			response.PDUs = make(map[string]gomatrixserverlib.PDUResult)
			for _, pdu := range transaction.PDUs {
				var header struct {
					RoomID string `json:"room_id"`
				}
				if err = json.Unmarshal(pdu, &header); err != nil {
					log.Printf("complement: Transaction '%s': Failed to extract room ID from event: %s", transaction.TransactionID, err.Error())

					// We don't know the event ID at this point so we can't return the
					// failure in the PDU results
					continue
				}

				// Retrieve the room version from the server
				room := srv.rooms[header.RoomID]
				if room == nil {
					// An invalid room ID may have been provided
					log.Printf("complement: Transaction '%s': Failed to find local room: %s", transaction.TransactionID, header.RoomID)
					continue
				}
				roomVersion := gomatrixserverlib.RoomVersion(room.Version)

				var event *gomatrixserverlib.Event
				event, err = gomatrixserverlib.NewEventFromUntrustedJSON(pdu, roomVersion)
				if err != nil {
					// We were unable to verify or process this event.
					log.Printf(
						"complement: Transaction '%s': Unable to process event '%s': %s",
						transaction.TransactionID, event.EventID(), err.Error(),
					)

					// We still don't know the event ID, and cannot add the failure to the PDU results
					continue
				}

				// Store this PDU in the room's timeline
				room.AddEvent(event)

				// Add this PDU as a success to the response
				response.PDUs[event.EventID()] = gomatrixserverlib.PDUResult{}

				// Run the PDU callback function with this event
				if pduCallback != nil {
					pduCallback(event)
				}
			}

			for _, edu := range transaction.EDUs {
				// Run the EDU callback function with this EDU
				if eduCallback != nil {
					eduCallback(edu)
				}
			}

			resp, err := json.Marshal(response)
			if err != nil {
				log.Printf("complement: Transaction '%s': Failed to marshal JSON response: %s", transaction.TransactionID, err.Error())
				w.WriteHeader(500)
				w.Write([]byte(fmt.Sprintf(`complement: failed to marshal JSON response: %s`, err)))
				return
			}
			w.WriteHeader(200)
			w.Write(resp)
		})).Methods("PUT")
	}
}
// HandleTransactionRequests is an option which will process GET /_matrix/federation/v1/send/{transactionID} requests universally when requested.
// pduCallback and eduCallback are functions that if non-nil will be called and passed each PDU or EDU event received in the transaction
HandleTransactionRequests is an option which will process GET /_matrix/federation/v1/send/{transactionID} requests universally when requested.
pduCallback and eduCallback are functions that if non-nil will be called and passed each PDU or EDU event received in the transaction
// HandleTransactionRequests is an option which will process GET / _matrix / federation / v1 / send / { transactionID } requests universally when requested . // pduCallback and eduCallback are functions that if non - nil will be called and passed each PDU or EDU event received in the transaction
func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCallback func(gomatrixserverlib.EDU)) func(*Server) {
	return func(srv *Server) {
		srv.mux.Handle("/_matrix/federation/v1/send/{transactionID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			vars := mux.Vars(req)
			transactionID := vars["transactionID"]
			fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
				req, time.Now(), gomatrixserverlib.ServerName(srv.ServerName), srv.keyRing,
			)
			if fedReq == nil {
				log.Printf(
					"complement: Transaction '%s': HTTP Code %d. Invalid http request: %s",
					transactionID, errResp.Code, errResp.JSON,
				)
				w.WriteHeader(errResp.Code)
				b, _ := json.Marshal(errResp.JSON)
				w.Write(b)
				return
			}
			var transaction gomatrixserverlib.Transaction
			err := json.Unmarshal(fedReq.Content(), &transaction)
			if err != nil {
				log.Printf(
					"complement: Transaction '%s': Unable to unmarshal transaction body bytes into Transaction object: %s",
					transaction.TransactionID, err.Error(),
				)
				errResp := util.MessageResponse(400, err.Error())
				w.WriteHeader(errResp.Code)
				b, _ := json.Marshal(errResp.JSON)
				w.Write(b)
				return
			}
			transaction.TransactionID = gomatrixserverlib.TransactionID(transactionID)
			if len(transaction.PDUs) > 50 || len(transaction.EDUs) > 100 {
				log.Printf(
					"complement: Transaction '%s': Transaction too large. PDUs: %d/50, EDUs: %d/100",
					transaction.TransactionID, len(transaction.PDUs), len(transaction.EDUs),
				)
				errResp := util.MessageResponse(400, "Transactions are limited to 50 PDUs and 100 EDUs")
				w.WriteHeader(errResp.Code)
				b, _ := json.Marshal(errResp.JSON)
				w.Write(b)
				return
			}
			response := gomatrixserverlib.RespSend{}
			response.PDUs = make(map[string]gomatrixserverlib.PDUResult)
			for _, pdu := range transaction.PDUs {
				var header struct {
					RoomID string `json:"room_id"`
				}
				if err = json.Unmarshal(pdu, &header); err != nil {
					log.Printf("complement: Transaction '%s': Failed to extract room ID from event: %s", transaction.TransactionID, err.Error())
					continue
				}
				room := srv.rooms[header.RoomID]
				if room == nil {
					log.Printf("complement: Transaction '%s': Failed to find local room: %s", transaction.TransactionID, header.RoomID)
					continue
				}
				roomVersion := gomatrixserverlib.RoomVersion(room.Version)
				var event *gomatrixserverlib.Event
				event, err = gomatrixserverlib.NewEventFromUntrustedJSON(pdu, roomVersion)
				if err != nil {
					log.Printf(
						"complement: Transaction '%s': Unable to process event '%s': %s",
						transaction.TransactionID, event.EventID(), err.Error(),
					)
					continue
				}
				room.AddEvent(event)
				response.PDUs[event.EventID()] = gomatrixserverlib.PDUResult{}
				if pduCallback != nil {
					pduCallback(event)
				}
			}
			for _, edu := range transaction.EDUs {
				if eduCallback != nil {
					eduCallback(edu)
				}
			}
			resp, err := json.Marshal(response)
			if err != nil {
				log.Printf("complement: Transaction '%s': Failed to marshal JSON response: %s", transaction.TransactionID, err.Error())
				w.WriteHeader(500)
				w.Write([]byte(fmt.Sprintf(`complement: failed to marshal JSON response: %s`, err)))
				return
			}
			w.WriteHeader(200)
			w.Write(resp)
		})).Methods("PUT")
	}
}
func HandleTransactionRequests ( pduCallback func ( * gomatrixserverlib . Event ) , eduCallback func ( gomatrixserverlib . EDU ) ) func ( * Server ) { return func ( srv * Server ) { srv . mux . Handle ( " " , http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) { vars := mux . Vars ( req ) transactionID := vars [ " " ] fedReq , errResp := gomatrixserverlib . VerifyHTTPRequest ( req , time . Now ( ) , gomatrixserverlib . ServerName ( srv . ServerName ) , srv . keyRing , ) if fedReq == nil { log . Printf ( " " , transactionID , errResp . Code , errResp . JSON , ) w . WriteHeader ( errResp . Code ) b , _ := json . Marshal ( errResp . JSON ) w . Write ( b ) return } var transaction gomatrixserverlib . Transaction err := json . Unmarshal ( fedReq . Content ( ) , & transaction ) if err != nil { log . Printf ( " " , transaction . TransactionID , err . Error ( ) , ) errResp := util . MessageResponse ( 400 , err . Error ( ) ) w . WriteHeader ( errResp . Code ) b , _ := json . Marshal ( errResp . JSON ) w . Write ( b ) return } transaction . TransactionID = gomatrixserverlib . TransactionID ( transactionID ) if len ( transaction . PDUs ) > 50 || len ( transaction . EDUs ) > 100 { log . Printf ( " " , transaction . TransactionID , len ( transaction . PDUs ) , len ( transaction . EDUs ) , ) errResp := util . MessageResponse ( 400 , " " ) w . WriteHeader ( errResp . Code ) b , _ := json . Marshal ( errResp . JSON ) w . Write ( b ) return } response := gomatrixserverlib . RespSend { } response . PDUs = make ( map [ string ] gomatrixserverlib . PDUResult ) for _ , pdu := range transaction . PDUs { var header struct { RoomID string `json:"room_id"` } if err = json . Unmarshal ( pdu , & header ) ; err != nil { log . Printf ( " " , transaction . TransactionID , err . Error ( ) ) continue } room := srv . rooms [ header . RoomID ] if room == nil { log . Printf ( " " , transaction . TransactionID , header . RoomID ) continue } roomVersion := gomatrixserverlib . RoomVersion ( room . Version ) var event * gomatrixserverlib . Event event , err = gomatrixserverlib . NewEventFromUntrustedJSON ( pdu , roomVersion ) if err != nil { log . Printf ( " " , transaction . TransactionID , event . EventID ( ) , err . Error ( ) , ) continue } room . AddEvent ( event ) response . PDUs [ event . EventID ( ) ] = gomatrixserverlib . PDUResult { } if pduCallback != nil { pduCallback ( event ) } } for _ , edu := range transaction . EDUs { if eduCallback != nil { eduCallback ( edu ) } } resp , err := json . Marshal ( response ) if err != nil { log . Printf ( " " , transaction . TransactionID , err . Error ( ) ) w . WriteHeader ( 500 ) w . Write ( [ ] byte ( fmt . Sprintf ( `complement: failed to marshal JSON response: %s` , err ) ) ) return } w . WriteHeader ( 200 ) w . Write ( resp ) } ) ) . Methods ( " " ) } }
HandleTransactionRequests is an option which will process GET /_matrix/federation/v1/send/{transactionID} requests universally when requested.
HandleTransactionRequests is an option which will process GET / _matrix / federation / v1 / send / { transactionID } requests universally when requested .
// Extract the transaction ID from the request vars // Check federation signature // Unmarshal the request body into a transaction object // Transactions are limited in size; they can have at most 50 PDUs and 100 EDUs. // https://matrix.org/docs/spec/server_server/latest#transactions // Construct a response and fill as we process each PDU // We don't know the event ID at this point so we can't return the // failure in the PDU results // Retrieve the room version from the server // An invalid room ID may have been provided // We were unable to verify or process this event. // We still don't know the event ID, and cannot add the failure to the PDU results // Store this PDU in the room's timeline // Add this PDU as a success to the response // Run the PDU callback function with this event // Run the EDU callback function with this EDU