dicomweb

package
v0.0.0-...-1098021 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 18, 2026 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Overview

Package dicomweb provides neutral DICOMweb client and embeddable server primitives for QIDO-RS, WADO-RS, and STOW-RS endpoints.

The package owns reusable request construction, response parsing, typed HTTP/DICOMweb errors, and bearer-token injection. TokenManager provides an in-memory access-token cache with serialized refresh and one safe retry after a challenged replayable request. Applications remain responsible for endpoint profiles, OAuth2/OIDC protocol flows, OS-protected credential persistence, authorization policy, jobs, archive import/export, and user-facing state.

Server is deny-by-default: callers must provide an Authorizer or explicitly set AllowUnauthenticated. It supplies bounded routing, DICOM JSON response validation, multipart streaming, complete-request STOW staging, graceful shutdown, and PHI-free audit events. Storage identity and duplicate policy are atomic backend responsibilities. See docs/DICOMWEB_SERVER.md for the implemented PS3.18 profile and intentional limitations.

Index

Constants

View Source
const (
	// DefaultTimeout bounds a single DICOMweb request when Options.Timeout is unset.
	DefaultTimeout = 20 * time.Second
	// DefaultMaxBodyBytes bounds response bodies when Options.MaxBodyBytes is unset.
	DefaultMaxBodyBytes = int64(512 << 20)
)

Variables

View Source
var (
	// ErrInvalidServerOptions reports an invalid or incomplete server configuration.
	ErrInvalidServerOptions = errors.New("dicomweb: invalid server options")
	// ErrInvalidRequest reports a malformed DICOMweb request.
	ErrInvalidRequest = errors.New("dicomweb: invalid request")
	// ErrUnauthorized reports that authentication is required or failed.
	ErrUnauthorized = errors.New("dicomweb: unauthorized")
	// ErrForbidden reports that the authenticated caller is not authorized.
	ErrForbidden = errors.New("dicomweb: forbidden")
	// ErrNotFound reports that a requested DICOM resource does not exist.
	ErrNotFound = errors.New("dicomweb: resource not found")
	// ErrConflict reports a store or resource identity conflict.
	ErrConflict = errors.New("dicomweb: conflict")
	// ErrUnsupported reports an unsupported resource, media type, or operation.
	ErrUnsupported = errors.New("dicomweb: unsupported operation")
	// ErrResourceLimit reports a finite server resource limit.
	ErrResourceLimit = errors.New("dicomweb: resource limit exceeded")
	// ErrBackend reports a backend failure whose details must not cross the HTTP boundary.
	ErrBackend = errors.New("dicomweb: backend failure")
)
View Source
var (
	// ErrBearerTokenUnavailable reports that a dynamic bearer source could not
	// provide a usable access token. Provider errors are deliberately redacted.
	ErrBearerTokenUnavailable = errors.New("DICOMweb bearer token unavailable")
)

Functions

func InstanceSearchParams

func InstanceSearchParams(criteria InstanceSearchCriteria) (url.Values, error)

InstanceSearchParams converts neutral instance criteria into QIDO-RS query params.

func InstanceSearchReturnFields

func InstanceSearchReturnFields() []string

InstanceSearchReturnFields returns the default QIDO-RS instance return fields.

func SeriesSearchParams

func SeriesSearchParams(criteria SeriesSearchCriteria) (url.Values, error)

SeriesSearchParams converts neutral series criteria into QIDO-RS query params.

func SeriesSearchReturnFields

func SeriesSearchReturnFields() []string

SeriesSearchReturnFields returns the default QIDO-RS series return fields.

func StudySearchParams

func StudySearchParams(criteria StudySearchCriteria) (url.Values, error)

StudySearchParams converts neutral study criteria into QIDO-RS query params.

func StudySearchReturnFields

func StudySearchReturnFields() []string

StudySearchReturnFields returns the default QIDO-RS study return fields.

Types

type AccessToken

type AccessToken struct {
	Expiry time.Time `json:"expiry,omitempty"`
	// contains filtered or unexported fields
}

AccessToken keeps the bearer value private while exposing only non-secret lifecycle metadata.

func NewAccessToken

func NewAccessToken(value string, expiry time.Time) (AccessToken, error)

NewAccessToken creates an in-memory bearer token. The token value is never serialized or included in String/GoString output.

func (AccessToken) GoString

func (t AccessToken) GoString() string

GoString redacts the bearer value from %#v formatting and crash diagnostics.

func (AccessToken) MarshalJSON

func (t AccessToken) MarshalJSON() ([]byte, error)

MarshalJSON emits lifecycle metadata but never the bearer value.

func (AccessToken) String

func (t AccessToken) String() string

String redacts the bearer value from ordinary formatting and logs.

func (AccessToken) Value

func (t AccessToken) Value() string

Value returns the bearer value for an Authorization header.

type AuditEvent

type AuditEvent struct {
	Operation  Operation     `json:"operation"`
	RequestID  string        `json:"request_id,omitempty"`
	StatusCode int           `json:"status_code"`
	ItemCount  int           `json:"item_count,omitempty"`
	Duration   time.Duration `json:"duration"`
	ErrorCode  string        `json:"error_code,omitempty"`
}

AuditEvent contains only closed-schema operational metadata. It deliberately omits UIDs, paths, query values, DICOM attributes, remote error text, and authorization details.

type Authorizer

type Authorizer func(context.Context, *http.Request, Operation) error

Authorizer authorizes one request after routing but before backend work. Implementations may inspect the request, including route UIDs and query parameters, but should not retain them in logs. Return ErrUnauthorized or ErrForbidden to select the corresponding HTTP status.

type BearerTokenSource

type BearerTokenSource interface {
	Token(context.Context) (AccessToken, error)
}

BearerTokenSource supplies an access token for one DICOMweb request.

type BulkDataBackend

type BulkDataBackend interface {
	RetrieveBulkData(context.Context, BulkDataRequest) (BulkDataPart, error)
}

BulkDataBackend resolves authorized same-origin bulk data tokens.

type BulkDataPart

type BulkDataPart struct {
	ContentType string
	Reader      io.ReadCloser
	Size        int64
}

BulkDataPart is one bulk data stream owned and closed by the server.

type BulkDataRequest

type BulkDataRequest struct {
	Token  string
	Accept []MediaPreference
}

BulkDataRequest contains an opaque, backend-defined token from an authorized same-origin BulkDataURI. The core server never creates public BulkDataURIs.

type Client

type Client struct {
	Endpoint Endpoint
	Options  Options
}

Client is a neutral DICOMweb client for one endpoint.

func (Client) InstanceMetadata

func (c Client) InstanceMetadata(ctx context.Context, ref InstanceRef) ([]Dataset, error)

InstanceMetadata retrieves raw WADO-RS metadata for one instance.

func (Client) RetrieveFrames

func (c Client) RetrieveFrames(ctx context.Context, ref InstanceRef, frames []int, opts RetrieveOptions) ([]FramePart, error)

RetrieveFrames fetches selected one-based frames with WADO-RS. The response remains frame-scoped; callers never need to retrieve or decode the complete multi-frame instance.

func (Client) RetrieveInstance

func (c Client) RetrieveInstance(ctx context.Context, ref InstanceRef) ([]ObjectPart, error)

RetrieveInstance retrieves a WADO-RS DICOM object as one or more object parts.

func (Client) RetrieveInstanceStreamWithOptions

func (c Client) RetrieveInstanceStreamWithOptions(ctx context.Context, ref InstanceRef, opts RetrieveOptions, handle func(ObjectPartStream) error) error

RetrieveInstanceStreamWithOptions retrieves a WADO-RS DICOM object and streams each object part to handle.

func (Client) RetrieveInstanceWithOptions

func (c Client) RetrieveInstanceWithOptions(ctx context.Context, ref InstanceRef, opts RetrieveOptions) ([]ObjectPart, error)

RetrieveInstanceWithOptions retrieves a WADO-RS DICOM object with explicit media/transfer-syntax preferences.

func (Client) RetrieveSeriesStreamWithOptions

func (c Client) RetrieveSeriesStreamWithOptions(ctx context.Context, studyInstanceUID, seriesInstanceUID string, opts RetrieveOptions, handle func(LocatedObjectPartStream) error) error

RetrieveSeriesStreamWithOptions streams every Part 10 object in a WADO-RS series response.

func (Client) RetrieveStudyStreamWithOptions

func (c Client) RetrieveStudyStreamWithOptions(ctx context.Context, studyInstanceUID string, opts RetrieveOptions, handle func(LocatedObjectPartStream) error) error

RetrieveStudyStreamWithOptions streams every Part 10 object in a WADO-RS study response.

func (Client) SearchInstances

func (c Client) SearchInstances(ctx context.Context, studyInstanceUID, seriesInstanceUID string, params url.Values) ([]Dataset, error)

SearchInstances performs a QIDO-RS instance search for one series and returns raw DICOM JSON datasets.

func (Client) SearchSeries

func (c Client) SearchSeries(ctx context.Context, studyInstanceUID string, params url.Values) ([]Dataset, error)

SearchSeries performs a QIDO-RS series search for one study and returns raw DICOM JSON datasets.

func (Client) SearchStudies

func (c Client) SearchStudies(ctx context.Context, params url.Values) ([]Dataset, error)

SearchStudies performs a QIDO-RS study search and returns raw DICOM JSON datasets.

func (Client) SeriesMetadata

func (c Client) SeriesMetadata(ctx context.Context, studyInstanceUID, seriesInstanceUID string) ([]InstanceRef, error)

SeriesMetadata retrieves WADO-RS series metadata and returns instance references.

func (Client) SeriesMetadataDatasets

func (c Client) SeriesMetadataDatasets(ctx context.Context, studyInstanceUID, seriesInstanceUID string) ([]Dataset, error)

SeriesMetadataDatasets retrieves raw WADO-RS series metadata datasets.

func (Client) StoreInstances

func (c Client) StoreInstances(ctx context.Context, instances []StoreInstance) (StoreResult, error)

StoreInstances stores DICOM objects with STOW-RS multipart upload.

func (Client) StoreInstancesToStudy

func (c Client) StoreInstancesToStudy(ctx context.Context, studyInstanceUID string, instances []StoreInstance) (StoreResult, error)

StoreInstancesToStudy stores DICOM objects through the study-scoped STOW-RS route.

func (Client) StudyMetadata

func (c Client) StudyMetadata(ctx context.Context, studyInstanceUID string) ([]InstanceRef, error)

StudyMetadata retrieves WADO-RS study metadata and returns instance references.

func (Client) StudyMetadataDatasets

func (c Client) StudyMetadataDatasets(ctx context.Context, studyInstanceUID string) ([]Dataset, error)

StudyMetadataDatasets retrieves raw WADO-RS study metadata datasets.

func (Client) Verify

func (c Client) Verify(ctx context.Context) (VerifyResult, error)

Verify performs a light QIDO-RS study request to verify endpoint reachability.

type Dataset

type Dataset = dicomjson.Dataset

Dataset is a raw DICOM JSON dataset keyed by uppercase tag hex.

type Element

type Element = dicomjson.Element

Element is a raw DICOM JSON element.

type Endpoint

type Endpoint struct {
	BaseURL  string
	QIDOPath string
	WADOPath string
	STOWPath string
}

Endpoint describes a DICOMweb base URL and optional service-specific paths.

func (Endpoint) FramesURL

func (e Endpoint) FramesURL(ref InstanceRef, frames []int) (*url.URL, error)

FramesURL builds the WADO-RS RetrieveFrames URL. Frame numbers are one-based and duplicates are rejected to keep response-to-request mapping unambiguous.

func (Endpoint) InstanceMetadataURL

func (e Endpoint) InstanceMetadataURL(ref InstanceRef) (*url.URL, error)

InstanceMetadataURL builds the WADO-RS instance metadata URL.

func (Endpoint) InstanceSearchURL

func (e Endpoint) InstanceSearchURL(studyInstanceUID, seriesInstanceUID string, params url.Values) (*url.URL, error)

InstanceSearchURL builds the QIDO-RS instance search URL for a series.

func (Endpoint) InstanceURL

func (e Endpoint) InstanceURL(ref InstanceRef) (*url.URL, error)

InstanceURL builds the WADO-RS object retrieval URL.

func (Endpoint) SeriesMetadataURL

func (e Endpoint) SeriesMetadataURL(studyInstanceUID, seriesInstanceUID string) (*url.URL, error)

SeriesMetadataURL builds the WADO-RS series metadata URL.

func (Endpoint) SeriesSearchURL

func (e Endpoint) SeriesSearchURL(studyInstanceUID string, params url.Values) (*url.URL, error)

SeriesSearchURL builds the QIDO-RS series search URL for a study.

func (Endpoint) SeriesURL

func (e Endpoint) SeriesURL(studyInstanceUID, seriesInstanceUID string) (*url.URL, error)

SeriesURL builds the WADO-RS series retrieval URL.

func (Endpoint) StoreStudiesURL

func (e Endpoint) StoreStudiesURL() (*url.URL, error)

StoreStudiesURL builds the STOW-RS study storage URL.

func (Endpoint) StoreStudyURL

func (e Endpoint) StoreStudyURL(studyInstanceUID string) (*url.URL, error)

StoreStudyURL builds the study-scoped STOW-RS storage URL.

func (Endpoint) StudyMetadataURL

func (e Endpoint) StudyMetadataURL(studyInstanceUID string) (*url.URL, error)

StudyMetadataURL builds the WADO-RS study metadata URL.

func (Endpoint) StudySearchURL

func (e Endpoint) StudySearchURL(params url.Values) (*url.URL, error)

StudySearchURL builds the QIDO-RS study search URL.

func (Endpoint) StudyURL

func (e Endpoint) StudyURL(studyInstanceUID string) (*url.URL, error)

StudyURL builds the WADO-RS study retrieval URL.

type Error

type Error struct {
	Kind       ErrorKind
	URL        string
	StatusCode int
	Status     string
	Err        error
}

Error is a typed DICOMweb error.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying error.

type ErrorKind

type ErrorKind string

ErrorKind classifies DICOMweb failures.

const (
	ErrorKindInvalidEndpoint ErrorKind = "invalid_endpoint"
	ErrorKindRequestFailure  ErrorKind = "request_failure"
	ErrorKindTimeout         ErrorKind = "timeout"
	ErrorKindHTTPStatus      ErrorKind = "http_status"
	ErrorKindAuthStatus      ErrorKind = "auth_status"
	ErrorKindAuthToken       ErrorKind = "auth_token"
	ErrorKindDecodeResponse  ErrorKind = "decode_response"
)

type Existence

type Existence uint8

Existence describes whether a SOP Instance identity is present. Content equality and conflicts are decided atomically by StoreBackend.Store, which also receives the staged SHA-256 digest.

const (
	ExistenceAbsent Existence = iota
	ExistencePresent
)

type ExistenceBackend

type ExistenceBackend interface {
	Exists(context.Context, InstanceRef) (Existence, error)
}

ExistenceBackend supports planning and diagnostics. StoreBackend.Store must still perform its own atomic duplicate/conflict decision.

type FrameBackend

type FrameBackend interface {
	RetrieveFrames(context.Context, FrameRequest, func(FramePartStream) error) error
}

FrameBackend streams requested frame payloads in request order.

type FramePart

type FramePart struct {
	FrameNumber       int
	ContentType       string
	TransferSyntaxUID string
	Data              []byte
}

FramePart is one WADO-RS RetrieveFrames payload. FrameNumber is populated in request order because DICOMweb returns one MIME part per requested frame.

type FramePartStream

type FramePartStream struct {
	FrameNumber       int
	ContentType       string
	TransferSyntaxUID string
	Reader            io.Reader
	Size              int64
}

FramePartStream is one synchronous frame payload. If Reader implements io.Closer, the server closes it after yield returns.

type FrameRequest

type FrameRequest struct {
	Ref    InstanceRef
	Frames []int
	Accept []MediaPreference
}

FrameRequest identifies one-based frames and ordered media preferences.

type HTTPServerOptions

type HTTPServerOptions struct {
	ReadHeaderTimeout time.Duration
	ReadTimeout       time.Duration
	WriteTimeout      time.Duration
	IdleTimeout       time.Duration
	MaxHeaderBytes    int
}

HTTPServerOptions configures the optional net/http server owned by Server.

type InstanceMatch

type InstanceMatch struct {
	SOPInstanceUID    string
	SOPClassUID       string
	InstanceNumber    string
	Modality          string
	PatientID         string
	PatientName       string
	StudyInstanceUID  string
	SeriesInstanceUID string
}

InstanceMatch is a neutral QIDO-RS instance result extracted from DICOM JSON.

func InstanceMatchesFromDatasets

func InstanceMatchesFromDatasets(datasets []Dataset) []InstanceMatch

InstanceMatchesFromDatasets extracts neutral instance matches from raw DICOM JSON.

type InstanceRef

type InstanceRef struct {
	StudyInstanceUID  string
	SeriesInstanceUID string
	SOPInstanceUID    string
}

InstanceRef identifies a DICOM instance inside a study and series.

type InstanceSearchCriteria

type InstanceSearchCriteria struct {
	SOPInstanceUID string
	SOPClassUID    string
	InstanceNumber string
	Modality       string

	CustomFieldKeyword string
	CustomFieldValue   string
	Limit              int
}

InstanceSearchCriteria describes neutral QIDO-RS instance search inputs.

type LocatedObjectPartStream

type LocatedObjectPartStream struct {
	Part            ObjectPartStream
	ContentLocation string
}

LocatedObjectPartStream is one streamed object plus its same-origin Content-Location. Study and series retrieval use this type so callers can correlate each representation without reparsing its Part 10 payload.

type MediaPreference

type MediaPreference struct {
	MediaType         string
	TransferSyntaxUID string
	Quality           float64
	Multipart         bool
}

MediaPreference is one normalized Accept alternative passed to a backend.

type MetadataBackend

type MetadataBackend interface {
	Metadata(context.Context, MetadataRequest, func(Dataset) error) error
}

MetadataBackend streams DICOM JSON metadata datasets synchronously.

type MetadataLevel

type MetadataLevel string

MetadataLevel selects a WADO-RS metadata resource.

const (
	MetadataLevelStudy    MetadataLevel = "study"
	MetadataLevelSeries   MetadataLevel = "series"
	MetadataLevelInstance MetadataLevel = "instance"
)

type MetadataRequest

type MetadataRequest struct {
	Level             MetadataLevel
	StudyInstanceUID  string
	SeriesInstanceUID string
	SOPInstanceUID    string
}

MetadataRequest identifies a WADO-RS metadata resource.

type ObjectPart

type ObjectPart struct {
	ContentType       string
	TransferSyntaxUID string
	Data              []byte
}

ObjectPart is one WADO-RS DICOM object payload.

type ObjectPartStream

type ObjectPartStream struct {
	ContentType       string
	TransferSyntaxUID string
	Reader            io.Reader
}

ObjectPartStream is one WADO-RS DICOM object payload streamed from the HTTP response.

type Operation

type Operation string

Operation is a PHI-free authorization and audit operation identifier.

const (
	OperationSearchStudies    Operation = "search_studies"
	OperationSearchSeries     Operation = "search_series"
	OperationSearchInstances  Operation = "search_instances"
	OperationRetrieveStudy    Operation = "retrieve_study"
	OperationRetrieveSeries   Operation = "retrieve_series"
	OperationRetrieveInstance Operation = "retrieve_instance"
	OperationRetrieveMetadata Operation = "retrieve_metadata"
	OperationRetrieveFrames   Operation = "retrieve_frames"
	OperationRetrieveBulkData Operation = "retrieve_bulk_data"
	OperationStoreInstances   Operation = "store_instances"
	OperationUnknown          Operation = "unknown"
)

type Options

type Options struct {
	HTTPClient    *http.Client `json:"-"`
	Timeout       time.Duration
	MaxBodyBytes  int64
	BasicUsername string `json:"-"`
	BasicPassword string `json:"-"`
	BearerToken   string `json:"-"`
	// BearerTokenSource takes precedence over static bearer and basic
	// credentials. Failure to obtain a token fails closed without downgrade.
	BearerTokenSource BearerTokenSource `json:"-"`
}

Options configures HTTP transport, timeouts, response limits, and auth.

func (Options) GoString

func (o Options) GoString() string

GoString redacts credentials from %#v formatting and crash diagnostics.

func (Options) String

func (o Options) String() string

String reports configuration shape without exposing credentials.

type Response

type Response struct {
	URL        string
	StatusCode int
	Status     string
	Header     http.Header
	Body       []byte
}

Response captures common HTTP response details.

type RetrieveBackend

type RetrieveBackend interface {
	Retrieve(context.Context, RetrieveRequest, func(RetrievePart) error) error
}

RetrieveBackend streams Part 10 objects synchronously without whole-study buffering.

type RetrieveLevel

type RetrieveLevel string

RetrieveLevel selects a WADO-RS object resource.

const (
	RetrieveLevelStudy    RetrieveLevel = "study"
	RetrieveLevelSeries   RetrieveLevel = "series"
	RetrieveLevelInstance RetrieveLevel = "instance"
)

type RetrieveOptions

type RetrieveOptions struct {
	// TransferSyntaxUIDs lists DICOM transfer syntax preferences for the WADO-RS
	// Accept header. Use "*" to request the server's default/preserved transfer
	// syntax as a fallback.
	TransferSyntaxUIDs []string
}

RetrieveOptions configures WADO-RS object retrieval.

type RetrievePart

type RetrievePart struct {
	Ref               InstanceRef
	ContentType       string
	TransferSyntaxUID string
	Reader            io.ReadCloser
	Size              int64
}

RetrievePart is one synchronous WADO-RS object stream. The server always closes Reader after yield returns. Reader must remain valid until then.

type RetrieveRequest

type RetrieveRequest struct {
	Level             RetrieveLevel
	StudyInstanceUID  string
	SeriesInstanceUID string
	SOPInstanceUID    string
	Accept            []MediaPreference
}

RetrieveRequest identifies objects and the request's ordered media preferences.

type SearchBackend

type SearchBackend interface {
	Search(context.Context, SearchRequest, func(Dataset) error) (SearchResult, error)
}

SearchBackend streams DICOM JSON result datasets synchronously through yield.

type SearchFilter

type SearchFilter struct {
	Key    string
	Values []string
}

SearchFilter is one DICOM tag or keyword match parameter. Values preserve request order and multiplicity for backend-specific matching semantics.

type SearchLevel

type SearchLevel string

SearchLevel selects a PS3.18 QIDO-RS resource.

const (
	SearchLevelStudy    SearchLevel = "study"
	SearchLevelSeries   SearchLevel = "series"
	SearchLevelInstance SearchLevel = "instance"
)

type SearchRequest

type SearchRequest struct {
	Level             SearchLevel
	StudyInstanceUID  string
	SeriesInstanceUID string
	Filters           []SearchFilter
	IncludeFields     []string
	Limit             int
	LimitSet          bool
	// MaximumResults is the finite effective response cap after combining the
	// request limit with ServerLimits.MaxResults.
	MaximumResults        int
	Offset                int
	FuzzyMatching         bool
	EmptyValueMatching    bool
	MultipleValueMatching bool
}

SearchRequest is a validated, bounded QIDO-RS query.

type SearchResult

type SearchResult struct {
	Remaining                    *int
	FuzzyMatchingApplied         bool
	EmptyValueMatchingApplied    bool
	MultipleValueMatchingApplied bool
}

SearchResult describes server-side pagination and optional matching support. Remaining is nil when no pagination warning is needed. A backend that reaches MaximumResults must return the exact remaining count; the handler emits the PS3.18 Warning 299 response header when it is non-zero.

type SeriesMatch

type SeriesMatch struct {
	StudyInstanceUID  string
	SeriesInstanceUID string
	Modality          string
	SeriesNumber      string
	SeriesDescription string
	SeriesDate        string
	SeriesTime        string
	InstanceCount     string
}

SeriesMatch is a neutral QIDO-RS series result extracted from DICOM JSON.

func SeriesMatchesFromDatasets

func SeriesMatchesFromDatasets(datasets []Dataset) []SeriesMatch

SeriesMatchesFromDatasets extracts neutral series matches from raw DICOM JSON.

type SeriesSearchCriteria

type SeriesSearchCriteria struct {
	SeriesInstanceUID string
	Modality          string
	SeriesNumber      string
	SeriesDescription string

	SeriesDateFrom string
	SeriesDateTo   string
	SeriesTimeFrom string
	SeriesTimeTo   string

	CustomFieldKeyword string
	CustomFieldValue   string
	Limit              int
}

SeriesSearchCriteria describes neutral QIDO-RS series search inputs.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is an embeddable http.Handler and an optional owner of an http.Server.

func NewServer

func NewServer(options ServerOptions) (*Server, error)

NewServer constructs a bounded, deny-by-default DICOMweb handler.

func (*Server) Serve

func (s *Server) Serve(listener net.Listener) error

Serve serves the handler on listener. Only one owned server may run at once.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops an owned server. It is idempotent when Serve has not been called or has already returned.

type ServerLimits

type ServerLimits struct {
	MaxRequestBytes       int64
	MaxPartBytes          int64
	MaxDecodedPartBytes   int64
	MaxResponseBytes      int64
	MaxRequestURIBytes    int
	MaxHeaderBytes        int
	MaxPartHeaderBytes    int
	MaxQueryValueBytes    int
	MaxUIDBytes           int
	MaxJSONValueBytes     int
	MaxJSONValues         int
	MaxJSONDepth          int
	MaxParts              int
	MaxQueryFields        int
	MaxResults            int
	MaxOffset             int
	MaxFrames             int
	MaxConcurrentRequests int
	MaxDuration           time.Duration
}

ServerLimits bounds parsing, buffering, concurrency, and response work. Zero fields receive finite defaults from DefaultServerLimits.

func DefaultServerLimits

func DefaultServerLimits() ServerLimits

DefaultServerLimits returns conservative finite limits suitable for an embedded service. Applications should tune these to their deployment.

type ServerOptions

type ServerOptions struct {
	Backend any
	Limits  ServerLimits
	// ServiceRoot is the externally visible mount path (for example,
	// "/dicomweb"). It is used for same-origin URLs and Warning headers. Mount
	// the handler with http.StripPrefix when it is non-empty.
	ServiceRoot string

	// Authorize is called before any backend work. When it is nil, requests are
	// rejected unless AllowUnauthenticated is explicitly true.
	Authorize            Authorizer
	AllowUnauthenticated bool

	// Middleware may add deployment-specific authentication, CORS, tracing, or
	// telemetry around the bounded core handler. No CORS policy is enabled by
	// default.
	Middleware func(http.Handler) http.Handler
	RequestID  func(*http.Request) string
	Audit      func(context.Context, AuditEvent)

	StorePolicy StorePolicy
	// SpoolDirectory selects temporary storage for bounded STOW request staging
	// and QIDO/metadata response spooling. Empty uses the operating system
	// temporary directory. These 0600 files may contain PHI and the deployment
	// must place them on appropriately protected storage.
	SpoolDirectory string
	// SpoolRetentionAge removes inactive server-owned spool files older than
	// this age when NewServer starts. Zero uses a finite default.
	SpoolRetentionAge time.Duration
	// SpoolAggregateQuotaBytes removes the oldest inactive server-owned spool
	// files until aggregate usage is at or below this value. Zero uses a finite
	// default. Active and unrelated entries are never removed.
	SpoolAggregateQuotaBytes int64
	HTTP                     HTTPServerOptions
}

ServerOptions configures an embeddable DICOMweb handler.

type StoreBackend

type StoreBackend interface {
	Store(context.Context, StoreRequest) StoreOutcome
}

StoreBackend stores one multipart part synchronously and atomically.

type StoreInstance

type StoreInstance struct {
	SOPClassUID    string
	SOPInstanceUID string
	Path           string
	// Data is the in-memory DICOM Part 10 payload. Prefer Reader or Open for
	// large objects so STOW-RS can stream the multipart body.
	Data []byte
	// Reader streams the DICOM Part 10 payload for this instance. It is used
	// when Open is nil and Data is empty.
	Reader io.Reader
	// Open returns a fresh DICOM Part 10 payload reader. It is preferred over
	// Reader so callers can open files lazily during multipart streaming.
	Open func() (io.ReadCloser, error)
}

StoreInstance is one DICOM object to include in a STOW-RS upload.

type StoreItem

type StoreItem struct {
	SOPClassUID    string
	SOPInstanceUID string
	RetrieveURL    string
	WarningReason  uint16
	FailureReason  uint16
}

StoreItem describes one SOP item reported in a STOW-RS response.

type StoreOutcome

type StoreOutcome struct {
	Status        StoreStatus
	Ref           InstanceRef
	SOPClassUID   string
	WarningReason uint16
	FailureReason uint16
	Err           error
}

StoreOutcome is one STOW-RS instance disposition. Err is never exposed to HTTP clients or audit hooks.

type StorePolicy

type StorePolicy string

StorePolicy controls duplicate SOP Instance handling. Atomic identity, duplicate, and conflict resolution belongs inside StoreBackend.Store.

const (
	StorePolicyRejectDuplicate StorePolicy = "reject_duplicate"
	StorePolicyIdempotent      StorePolicy = "idempotent"
)

type StoreRequest

type StoreRequest struct {
	Index             int
	RouteStudyUID     string
	Ref               InstanceRef
	SOPClassUID       string
	ContentType       string
	TransferSyntaxUID string
	Policy            StorePolicy
	Reader            io.Reader
	Size              int64
	SHA256            [32]byte
}

StoreRequest is one bounded multipart part. Store must consume Reader before returning and atomically decide duplicate/conflict policy before commit.

type StoreResult

type StoreResult struct {
	Response
	Stored []StoreItem
	Failed []StoreItem
}

StoreResult describes a STOW-RS response.

func StoreResultFromDICOMJSON

func StoreResultFromDICOMJSON(data []byte) (StoreResult, error)

StoreResultFromDICOMJSON parses a STOW-RS DICOM JSON response dataset.

type StoreStatus

type StoreStatus string

StoreStatus is one backend-selected atomic storage disposition.

const (
	StoreStatusStored    StoreStatus = "stored"
	StoreStatusWarning   StoreStatus = "warning"
	StoreStatusDuplicate StoreStatus = "duplicate"
	StoreStatusConflict  StoreStatus = "conflict"
	StoreStatusFailed    StoreStatus = "failed"
)

type StudyMatch

type StudyMatch struct {
	PatientName      string
	PatientID        string
	PatientBirthDate string

	StudyDate  string
	StudyTime  string
	ImageCount string

	StudyDescription       string
	AccessionNumber        string
	ReferringPhysicianName string
	InstitutionName        string
	PatientComments        string
	StudyStatusID          string
	BodyPartExamined       string
	WorkListStatus         string
	StudyInstanceUID       string
	Modalities             string
}

StudyMatch is a neutral QIDO-RS study result extracted from DICOM JSON.

func StudyMatchesFromDatasets

func StudyMatchesFromDatasets(datasets []Dataset) []StudyMatch

StudyMatchesFromDatasets extracts neutral study matches from raw DICOM JSON.

type StudySearchCriteria

type StudySearchCriteria struct {
	PatientName      string
	PatientID        string
	PatientBirthDate string

	StudyDateFrom string
	StudyDateTo   string
	StudyTimeFrom string
	StudyTimeTo   string

	StudyDescription       string
	AccessionNumber        string
	ReferringPhysicianName string
	InstitutionName        string
	PatientComments        string
	StudyStatusID          string
	BodyPartExamined       string
	WorkListStatus         string
	Modality               string
	StudyInstanceUID       string

	CustomFieldKeyword string
	CustomFieldValue   string
	Limit              int
}

StudySearchCriteria describes neutral QIDO-RS study search inputs.

type TokenManager

type TokenManager struct {
	// contains filtered or unexported fields
}

TokenManager caches access tokens in memory and serializes refresh calls.

func NewTokenManager

func NewTokenManager(initial AccessToken, refresh TokenRefreshFunc) *TokenManager

NewTokenManager constructs a concurrency-safe, in-memory access-token manager. An empty initial token is allowed when refresh is configured.

func (*TokenManager) GoString

func (m *TokenManager) GoString() string

GoString redacts token state from %#v formatting and crash diagnostics.

func (*TokenManager) Invalidate

func (m *TokenManager) Invalidate(challenged AccessToken)

Invalidate drops the cached token only when it matches the challenged token.

func (*TokenManager) Logout

func (m *TokenManager) Logout()

Logout permanently disables the manager and removes its in-memory access token. Persistent refresh credentials are owned by the caller.

func (*TokenManager) Status

func (m *TokenManager) Status() TokenStatus

Status returns non-secret token lifecycle information.

func (*TokenManager) String

func (m *TokenManager) String() string

String reports non-secret lifecycle state for diagnostics.

func (*TokenManager) Token

func (m *TokenManager) Token(ctx context.Context) (AccessToken, error)

Token returns a cached token or performs one serialized refresh. Waiting callers may cancel independently.

type TokenRefreshFunc

type TokenRefreshFunc func(context.Context) (AccessToken, error)

TokenRefreshFunc obtains a new access token. Refresh-token persistence and OIDC protocol exchange remain outside the manager so callers can use OS-protected credential storage.

type TokenStatus

type TokenStatus struct {
	Authenticated bool
	Expiry        time.Time
	Refreshing    bool
}

TokenStatus exposes non-secret lifecycle state for product UI.

type VerifyResult

type VerifyResult struct {
	Response
	Duration  time.Duration
	StartedAt time.Time
}

VerifyResult describes a DICOMweb verify request.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL