mirror of
https://github.com/pikami/cosmium.git
synced 2026-06-12 23:37:02 +01:00
Initial RNTBD server implementation
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
package rntbd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/pikami/cosmium/api/headers"
|
||||
)
|
||||
|
||||
func (f *RntbdFrame) ToHttpRequest() *http.Request {
|
||||
req := &http.Request{
|
||||
Method: operationTypeToHttpMethod(f.OperationType),
|
||||
URL: &url.URL{Path: frameToPath(f)},
|
||||
Body: io.NopCloser(bytes.NewReader(f.Payload)),
|
||||
Header: http.Header{},
|
||||
}
|
||||
|
||||
switch f.OperationType {
|
||||
case RntbdOperationTypeQuery, RntbdOperationTypeSQLQuery:
|
||||
req.Header.Set(headers.Query, "true")
|
||||
case RntbdOperationTypeUpsert:
|
||||
req.Header.Set(headers.IsUpsert, "true")
|
||||
}
|
||||
|
||||
if ifMatch, ok := f.RequestHeaders[RntbdRequestHeaderMatch]; ok {
|
||||
if ifMatchString, ok := ifMatch.(string); ok {
|
||||
req.Header.Set(headers.IfMatch, ifMatchString)
|
||||
}
|
||||
}
|
||||
|
||||
if continuationToken, ok := f.RequestHeaders[RntbdRequestHeaderContinuationToken]; ok {
|
||||
if continuationTokenString, ok := continuationToken.(string); ok {
|
||||
req.Header.Set(headers.ContinuationToken, continuationTokenString)
|
||||
}
|
||||
}
|
||||
|
||||
if maxItemCount, ok := f.RequestHeaders[RntbdRequestHeaderPageSize]; ok {
|
||||
if maxItemCountString, ok := maxItemCount.(uint64); ok {
|
||||
req.Header.Set(headers.MaxItemCount, fmt.Sprintf("%d", maxItemCountString))
|
||||
}
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
func ToRntbdResponseFrame(responseWriter *httptest.ResponseRecorder) *RntbdResponseFrameBuilder {
|
||||
builder := &RntbdResponseFrameBuilder{}
|
||||
builder.SetStatusCode(uint16(responseWriter.Code))
|
||||
|
||||
if responseWriter.Header().Get(headers.ETag) != "" {
|
||||
builder.AddHeader(uint16(RntbdResponseHeaderETag), RntbdTokenTypeString, responseWriter.Header().Get(headers.ETag))
|
||||
}
|
||||
|
||||
if responseWriter.Header().Get(headers.ContinuationToken) != "" {
|
||||
builder.AddHeader(uint16(RntbdResponseHeaderContinuationToken), RntbdTokenTypeString, responseWriter.Header().Get(headers.ContinuationToken))
|
||||
}
|
||||
|
||||
if responseWriter.Header().Get(headers.ItemCount) != "" {
|
||||
itemCount, err := strconv.ParseUint(responseWriter.Header().Get(headers.ItemCount), 10, 32)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
builder.AddHeader(uint16(RntbdResponseHeaderItemCount), RntbdTokenTypeULong, uint32(itemCount))
|
||||
}
|
||||
|
||||
if responseWriter.Body.Len() > 0 {
|
||||
builder.AddHeader(uint16(RntbdResponseHeaderPayloadPresent), RntbdTokenTypeByte, []byte{1})
|
||||
builder.AddPayload(responseWriter.Body.Bytes())
|
||||
} else {
|
||||
builder.AddHeader(uint16(RntbdResponseHeaderPayloadPresent), RntbdTokenTypeByte, []byte{0})
|
||||
}
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
func operationTypeToHttpMethod(operationType RntbdOperationType) string {
|
||||
switch operationType {
|
||||
case RntbdOperationTypeRead,
|
||||
RntbdOperationTypeReadFeed:
|
||||
return http.MethodGet
|
||||
case RntbdOperationTypeCreate,
|
||||
RntbdOperationTypeUpsert,
|
||||
RntbdOperationTypeQuery,
|
||||
RntbdOperationTypeSQLQuery:
|
||||
return http.MethodPost
|
||||
case RntbdOperationTypeUpdate,
|
||||
RntbdOperationTypeReplace:
|
||||
return http.MethodPut
|
||||
case RntbdOperationTypeDelete:
|
||||
return http.MethodDelete
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Unknown operation type: %d", operationType))
|
||||
}
|
||||
|
||||
func frameToPath(frame *RntbdFrame) string {
|
||||
databaseName, databaseOk := frame.RequestHeaders[RntbdRequestHeaderDatabaseName]
|
||||
collectionName, collectionOk := frame.RequestHeaders[RntbdRequestHeaderCollectionName]
|
||||
documentName, documentOk := frame.RequestHeaders[RntbdRequestHeaderDocumentName]
|
||||
|
||||
urlPath := ""
|
||||
|
||||
if databaseOk {
|
||||
urlPath += fmt.Sprintf("/dbs/%s", databaseName)
|
||||
} else if frame.ResourceType == RntbdResourceTypeDatabase {
|
||||
urlPath += "/dbs"
|
||||
}
|
||||
|
||||
if collectionOk {
|
||||
urlPath += fmt.Sprintf("/colls/%s", collectionName)
|
||||
} else if frame.ResourceType == RntbdResourceTypeCollection {
|
||||
urlPath += "/colls"
|
||||
}
|
||||
|
||||
if documentOk {
|
||||
urlPath += fmt.Sprintf("/docs/%s", documentName)
|
||||
} else if frame.ResourceType == RntbdResourceTypeDocument {
|
||||
urlPath += "/docs"
|
||||
}
|
||||
|
||||
return urlPath
|
||||
}
|
||||
Reference in New Issue
Block a user