Documentation
¶
Index ¶
- Constants
- Variables
- func ClientCompatibilityTest(t *testing.T, server *Server)
- func Delete(server *Server, path string) error
- func Get[T any](server *Server, path string) (client.Meta[T], error)
- func GetList[T any](server *Server, path string) ([]client.Meta[T], error)
- func Patch[T any](server *Server, path string, item T) error
- func Push[T any](server *Server, path string, item T) (string, error)
- func Set[T any](server *Server, path string, item T) error
- func StorageAfterWriteTest(db storage.Database, t *testing.T)
- func StorageBatchSetTest(server *Server, t *testing.T, n int)
- func StorageBeforeReadTest(db storage.Database, t *testing.T)
- func StorageGetNRangeTest(server *Server, t *testing.T, n int)
- func StorageGetNTest(server *Server, t *testing.T, n int)
- func StorageKeysRangeTest(server *Server, t *testing.T, n int)
- func StorageListTest(server *Server, t *testing.T)
- func StorageObjectTest(server *Server, t *testing.T)
- func StorageSetGetDelTestBenchmark(db storage.Database, b *testing.B)
- func StreamBroadcastFilterTest(t *testing.T, server *Server)
- func StreamBroadcastForcePatchTest(t *testing.T, server *Server)
- func StreamBroadcastNoPatchTest(t *testing.T, server *Server)
- func StreamBroadcastPatchTest(t *testing.T, server *Server)
- func StreamBroadcastTest(t *testing.T, server *Server)
- func StreamGlobBroadcastConcurrentTest(t *testing.T, server *Server, n int)
- func StreamGlobBroadcastTest(t *testing.T, server *Server, n int)
- func StreamItemGlobBroadcastTest(t *testing.T, server *Server)
- func StreamLimitFilterTest(t *testing.T, server *Server)
- func Time() string
- func WatchStorageNoopTest(db storage.Database, t *testing.T)
- type Apply
- type ApplyList
- type ApplyObject
- type Block
- type EndpointConfig
- type FetchResult
- type FilterConfig
- type LimitFilterConfig
- type LimitFunc
- type MethodSpec
- type Methods
- type Notify
- type Params
- type Server
- func (server *Server) Active() bool
- func (server *Server) AfterWriteFilter(path string, apply Notify, cfg ...FilterConfig)
- func (server *Server) Close(sig os.Signal)
- func (server *Server) DeleteFilter(path string, apply Block, cfg ...FilterConfig)
- func (server *Server) Endpoint(cfg EndpointConfig)
- func (server *Server) LimitFilter(path string, cfg filters.LimitFilterConfig)
- func (server *Server) OpenFilter(name string, cfg ...FilterConfig)
- func (server *Server) ReadListFilter(path string, apply ApplyList, cfg ...FilterConfig)
- func (server *Server) ReadObjectFilter(path string, apply ApplyObject, cfg ...FilterConfig)
- func (server *Server) RegisterLimitFilter(lf *filters.LimitFilter, description string, schema map[string]any)
- func (server *Server) RegisterPreClose(cleanup func())
- func (server *Server) RegisterProxy(info ui.ProxyInfo)
- func (server *Server) RegisterProxyCleanup(cleanup func())
- func (server *Server) Start(address string)
- func (server *Server) StartWithError(address string) error
- func (server *Server) Validate() error
- func (server *Server) WaitClose()
- func (server *Server) WriteFilter(path string, apply Apply, cfg ...FilterConfig)
- type Vars
Examples ¶
Constants ¶
const ( OrderDesc = filters.OrderDesc // Most recent first (default) OrderAsc = filters.OrderAsc // Oldest first )
Order constants for LimitFilterConfig
Variables ¶
var ( ErrInvalidPath = errors.New("ooo: invalid path") ErrNotFound = errors.New("ooo: not found") ErrNoop = errors.New("ooo: noop") ErrGlobNotAllowed = errors.New("ooo: glob pattern not allowed for this operation") ErrGlobRequired = errors.New("ooo: glob pattern required for this operation") ErrInvalidStorageData = errors.New("ooo: invalid storage data (empty)") ErrInvalidPattern = errors.New("ooo: invalid pattern") ErrInvalidRange = errors.New("ooo: invalid range") ErrInvalidLimit = errors.New("ooo: invalid limit") ErrLockNotFound = errors.New("ooo: lock not found can't unlock") ErrCantLockGlob = errors.New("ooo: can't lock a glob pattern path") )
Storage errors
var ( ErrServerAlreadyActive = errors.New("ooo: server already active") ErrServerStartFailed = errors.New("ooo: server start failed") ErrForcePatchConflict = errors.New("ooo: ForcePatch and NoPatch cannot both be enabled") ErrNegativeWorkers = errors.New("ooo: Workers cannot be negative") ErrNegativeDeadline = errors.New("ooo: Deadline cannot be negative") )
Server errors
var ( ErrNotAuthorized = errors.New("ooo: request is not authorized") ErrInvalidKey = errors.New("ooo: key is not valid") ErrEmptyKey = errors.New("ooo: empty key") )
REST/HTTP errors
var ( ErrRouteNotDefined = errors.New("ooo: route not defined, static mode") ErrInvalidFilterResult = errors.New("ooo: invalid filter result") ErrReservedPath = errors.New("ooo: filter path conflicts with reserved UI paths") )
Filter errors
var ( NoopHook = filters.NoopHook NoopNotify = filters.NoopNotify NoopFilter = filters.NoopFilter NoopObjectFilter = filters.NoopObjectFilter NoopListFilter = filters.NoopListFilter )
Re-export filter functions from filters package
var ( ErrPathGlobRequired = errors.New("io: path glob required") ErrPathGlobNotAllowed = errors.New("io: path glob not allowed") )
var TEST_DATA = json.RawMessage(`{
"statuses": [
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Mon Sep 24 03:35:21 +0000 2012",
"id_str": "250075927172759552",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Aggressive Ponytail #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 250075927172759552,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDEEF6",
"profile_sidebar_border_color": "C0DEED",
"profile_background_tile": false,
"name": "Sean Cummings",
"profile_image_url": "http://a0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"created_at": "Mon Apr 26 06:01:55 +0000 2010",
"location": "LA, CA",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "137238150",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": true,
"contributors_enabled": false,
"favourites_count": 0,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"utc_offset": -28800,
"id": 137238150,
"profile_use_background_image": true,
"listed_count": 2,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 70,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme1/bg.png",
"profile_background_color": "C0DEED",
"verified": false,
"geo_enabled": true,
"time_zone": "Pacific Time (US & Canada)",
"description": "Born 330 Live 310",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme1/bg.png",
"statuses_count": 579,
"friends_count": 110,
"following": null,
"show_all_inline_media": false,
"screen_name": "sean_cummings"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:40:54 +0000 2012",
"id_str": "249292149810667520",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "FreeBandNames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Thee Namaste Nerdz. #FreeBandNames",
"metadata": {
"iso_language_code": "pl",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249292149810667520,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDFFCC",
"profile_sidebar_border_color": "BDDCAD",
"profile_background_tile": true,
"name": "Chaz Martenstein",
"profile_image_url": "http://a0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"created_at": "Tue Apr 07 19:05:07 +0000 2009",
"location": "Durham, NC",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "29516238",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "http://bullcityrecords.com/wnng/",
"indices": [
0,
32
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 8,
"url": "http://bullcityrecords.com/wnng/",
"profile_image_url_https": "https://si0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"utc_offset": -18000,
"id": 29516238,
"profile_use_background_image": true,
"listed_count": 118,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 2052,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"profile_background_color": "9AE4E8",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "You will come to Durham, North Carolina. I will sell you some records then, here in Durham, North Carolina. Fun will happen.",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"statuses_count": 7579,
"friends_count": 348,
"following": null,
"show_all_inline_media": true,
"screen_name": "bullcityrecords"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:30:20 +0000 2012",
"id_str": "249289491129438208",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
29,
43
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Mexican Heaven, Mexican Hell #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249289491129438208,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "99CC33",
"profile_sidebar_border_color": "829D5E",
"profile_background_tile": false,
"name": "Thomas John Wakeman",
"profile_image_url": "http://a0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"created_at": "Tue Sep 01 21:21:35 +0000 2009",
"location": "Kingston New York",
"follow_request_sent": null,
"profile_link_color": "D02B55",
"is_translator": false,
"id_str": "70789458",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 19,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"utc_offset": -18000,
"id": 70789458,
"profile_use_background_image": true,
"listed_count": 1,
"profile_text_color": "3E4415",
"lang": "en",
"followers_count": 63,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme5/bg.gif",
"profile_background_color": "352726",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "Science Fiction Writer, sort of. Likes Superheroes, Mole People, Alt. Timelines.",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme5/bg.gif",
"statuses_count": 1048,
"friends_count": 63,
"following": null,
"show_all_inline_media": false,
"screen_name": "MonkiesFist"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 22:51:18 +0000 2012",
"id_str": "249279667666817024",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "The Foolish Mortals #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249279667666817024,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "BFAC83",
"profile_sidebar_border_color": "615A44",
"profile_background_tile": true,
"name": "Marty Elmer",
"profile_image_url": "http://a0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"created_at": "Mon May 04 00:05:00 +0000 2009",
"location": "Wisconsin, USA",
"follow_request_sent": null,
"profile_link_color": "3B2A26",
"is_translator": false,
"id_str": "37539828",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "http://www.omnitarian.me",
"indices": [
0,
24
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 647,
"url": "http://www.omnitarian.me",
"profile_image_url_https": "https://si0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"utc_offset": -21600,
"id": 37539828,
"profile_use_background_image": true,
"listed_count": 52,
"profile_text_color": "000000",
"lang": "en",
"followers_count": 608,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"profile_background_color": "EEE3C4",
"verified": false,
"geo_enabled": false,
"time_zone": "Central Time (US & Canada)",
"description": "Cartoonist, Illustrator, and T-Shirt connoisseur",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"statuses_count": 3575,
"friends_count": 249,
"following": null,
"show_all_inline_media": true,
"screen_name": "Omnitarian"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//twitter.com/download/iphone%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for iPhone</a>",
"in_reply_to_status_id": null
}
],
"search_metadata": {
"max_id": 250126199840518145,
"since_id": 24012619984051000,
"refresh_url": "?since_id=250126199840518145&q=%23freebandnames&result_type=mixed&include_entities=1",
"next_results": "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed",
"count": 4,
"completed_in": 0.035,
"since_id_str": "24012619984051000",
"query": "%23freebandnames",
"max_id_str": "250126199840518145",
"something": "something 🧰"
}
}`)
https://gist.github.com/slaise/9b9d63e0d59e8c8923bbd9d53f5beb61 https://medium.com/geekculture/my-golang-json-evaluation-20a9ca6ef79c
var TEST_DATA_UPDATE = json.RawMessage(`{
"statuses": [
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Mon Sep 24 03:35:21 +0000 2012",
"id_str": "250075927172759552",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Aggressive Ponytail #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 250075927172759552,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDEEF6",
"profile_sidebar_border_color": "C0DEED",
"profile_background_tile": false,
"name": "Sean Cummings",
"profile_image_url": "http://a0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"created_at": "Mon Apr 26 06:01:55 +0000 2010",
"location": "LA, CA",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "137238150",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": true,
"contributors_enabled": false,
"favourites_count": 0,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2359746665/1v6zfgqo8g0d3mk7ii5s_normal.jpeg",
"utc_offset": -28800,
"id": 137238150,
"profile_use_background_image": true,
"listed_count": 2,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 70,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme1/bg.png",
"profile_background_color": "C0DEED",
"verified": false,
"geo_enabled": true,
"time_zone": "Pacific Time (US & Canada)",
"description": "Born 330 Live 310",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme1/bg.png",
"statuses_count": 579,
"friends_count": 110,
"following": null,
"show_all_inline_media": false,
"screen_name": "sean_cummings"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//itunes.apple.com/us/app/twitter/id409789998?mt=12%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for Mac</a>",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:40:54 +0000 2012",
"id_str": "249292149810667520",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "FreeBandNames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Thee Namaste Nerdz. #FreeBandNames",
"metadata": {
"iso_language_code": "pl",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249292149810667520,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "DDFFCC",
"profile_sidebar_border_color": "BDDCAD",
"profile_background_tile": true,
"name": "Chaz Martenstein",
"profile_image_url": "http://a0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"created_at": "Tue Apr 07 19:05:07 +0000 2009",
"location": "Durham, NC",
"follow_request_sent": null,
"profile_link_color": "0084B4",
"is_translator": false,
"id_str": "29516238",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "http://bullcityrecords.com/wnng/",
"indices": [
0,
32
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 8,
"url": "http://bullcityrecords.com/wnng/",
"profile_image_url_https": "https://si0.twimg.com/profile_images/447958234/Lichtenstein_normal.jpg",
"utc_offset": -18000,
"id": 29516238,
"profile_use_background_image": true,
"listed_count": 118,
"profile_text_color": "333333",
"lang": "en",
"followers_count": 2052,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"profile_background_color": "9AE4E8",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "You will come to Durham, North Carolina. I will sell you some records then, here in Durham, North Carolina. Fun will happen.",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/9423277/background_tile.bmp",
"statuses_count": 7579,
"friends_count": 348,
"following": null,
"show_all_inline_media": true,
"screen_name": "bullcityrecords"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 23:30:20 +0000 2012",
"id_str": "249289491129438208",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
29,
43
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "Mexican Heaven, Mexican Hell #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249289491129438208,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "99CC33",
"profile_sidebar_border_color": "829D5E",
"profile_background_tile": false,
"name": "Thomas John Wakeman",
"profile_image_url": "http://a0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"created_at": "Tue Sep 01 21:21:35 +0000 2009",
"location": "Kingston New York",
"follow_request_sent": null,
"profile_link_color": "D02B55",
"is_translator": false,
"id_str": "70789458",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "",
"indices": [
0,
0
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 19,
"url": null,
"profile_image_url_https": "https://si0.twimg.com/profile_images/2219333930/Froggystyle_normal.png",
"utc_offset": -18000,
"id": 70789458,
"profile_use_background_image": true,
"listed_count": 1,
"profile_text_color": "3E4415",
"lang": "en",
"followers_count": 63,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/images/themes/theme5/bg.gif",
"profile_background_color": "352726",
"verified": false,
"geo_enabled": false,
"time_zone": "Eastern Time (US & Canada)",
"description": "Science Fiction Writer, sort of. Likes Superheroes, Mole People, Alt. Timelines.",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme5/bg.gif",
"statuses_count": 1048,
"friends_count": 63,
"following": null,
"show_all_inline_media": false,
"screen_name": "MonkiesFist"
},
"in_reply_to_screen_name": null,
"source": "web",
"in_reply_to_status_id": null
},
{
"coordinates": null,
"favorited": false,
"truncated": false,
"created_at": "Fri Sep 21 22:51:18 +0000 2012",
"id_str": "249279667666817024",
"entities": {
"urls": [
],
"hashtags": [
{
"text": "freebandnames",
"indices": [
20,
34
]
}
],
"user_mentions": [
]
},
"in_reply_to_user_id_str": null,
"contributors": null,
"text": "The Foolish Mortals #freebandnames",
"metadata": {
"iso_language_code": "en",
"result_type": "recent"
},
"retweet_count": 0,
"in_reply_to_status_id_str": null,
"id": 249279667666817024,
"geo": null,
"retweeted": false,
"in_reply_to_user_id": null,
"place": null,
"user": {
"profile_sidebar_fill_color": "BFAC83",
"profile_sidebar_border_color": "615A44",
"profile_background_tile": true,
"name": "Marty Elmer",
"profile_image_url": "http://a0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"created_at": "Mon May 04 00:05:00 +0000 2009",
"location": "Wisconsin, USA",
"follow_request_sent": null,
"profile_link_color": "3B2A26",
"is_translator": false,
"id_str": "37539828",
"entities": {
"url": {
"urls": [
{
"expanded_url": null,
"url": "http://www.omnitarian.me",
"indices": [
0,
24
]
}
]
},
"description": {
"urls": [
]
}
},
"default_profile": false,
"contributors_enabled": false,
"favourites_count": 647,
"url": "http://www.omnitarian.me",
"profile_image_url_https": "https://si0.twimg.com/profile_images/1629790393/shrinker_2000_trans_normal.png",
"utc_offset": -21600,
"id": 37539828,
"profile_use_background_image": true,
"listed_count": 52,
"profile_text_color": "000000",
"lang": "en",
"followers_count": 608,
"protected": false,
"notifications": null,
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"profile_background_color": "EEE3C4",
"verified": false,
"geo_enabled": false,
"time_zone": "Central Time (US & Canada)",
"description": "Cartoonist, Illustrator, and T-Shirt connoisseur",
"default_profile_image": false,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/106455659/rect6056-9.png",
"statuses_count": 3575,
"friends_count": 249,
"following": null,
"show_all_inline_media": true,
"screen_name": "Omnitarian"
},
"in_reply_to_screen_name": null,
"source": "<a href=\"//twitter.com/download/iphone%5C%22\" rel=\"\\\"nofollow\\\"\">Twitter for iPhone</a>",
"in_reply_to_status_id": null
}
],
"search_metadata": {
"max_id": 250126199840518145,
"since_id": 24012619984051000,
"refresh_url": "?since_id=250126199840518145&q=%23freebandnames&result_type=mixed&include_entities=1",
"next_results": "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed",
"count": 4,
"completed_in": 0.035,
"since_id_str": "24012619984051000",
"query": "%23freebandnames",
"max_id_str": "250126199840518145",
"something": "something else 🧰"
}
}`)
Functions ¶
func ClientCompatibilityTest ¶
ClientCompatibilityTest covers the key behaviors expected by ooo-client: 1. Object lifecycle: create (updated=0) → update (updated>0) → delete (empty object) 2. List lifecycle: create → update → delete single item 3. Glob delete: multiple items deleted with single broadcast returning empty list 4. List sort order: newest first (descending by created) 5. Nested paths: box/*/things/* pattern matching
func Delete ¶
Delete removes an item at the specified path from storage. The path must not contain glob patterns.
func Patch ¶
Patch applies a partial update to an existing item at the specified path. The path must not contain glob patterns and the item must already exist. The patch is merged with the existing data using JSON merge semantics.
func StorageAfterWriteTest ¶
StorageAfterWriteTest tests that the AfterWrite callback is called on write operations
func StorageBeforeReadTest ¶
StorageBeforeReadTest tests that the BeforeRead callback is called on read operations
func StorageGetNRangeTest ¶
StorageGetNRangeTest testing storage GetN function
func StorageGetNTest ¶
StorageGetNTest testing storage GetN function
func StorageKeysRangeTest ¶
StorageKeysRangeTest testing storage KeysRange function
func StorageListTest ¶
StorageListTest testing storage function
func StorageObjectTest ¶
StorageObjectTest testing storage function
func StorageSetGetDelTestBenchmark ¶
StorageSetGetDelTest testing storage function
func StreamBroadcastFilterTest ¶
StreamBroadcastFilterTest testing stream function Note: This test uses raw websocket to verify snapshot/patch protocol behavior
func StreamBroadcastForcePatchTest ¶
StreamBroadcastForcePatchTest testing stream function Note: This test uses raw websocket to verify ForcePatch behavior (no snapshots after first)
func StreamBroadcastNoPatchTest ¶
StreamBroadcastNoPatchTest testing stream function Note: This test uses raw websocket to verify NoPatch behavior (all messages are snapshots)
func StreamBroadcastTest ¶
StreamBroadcastTest testing stream function Note: Uses raw websocket to verify patch protocol and meta.Object structure
func StreamGlobBroadcastTest ¶
StreamGlobBroadcastTest testing stream function Note: This test uses raw websocket to verify patch/snapshot protocol behavior
func StreamItemGlobBroadcastTest ¶
StreamItemGlobBroadcastTest testing stream function Note: Uses raw websocket to verify patch protocol and meta.Object structure
func StreamLimitFilterTest ¶
StreamLimitFilterTest tests that the LimitFilter correctly maintains the limit when items are inserted and broadcast to subscribed clients. The client should never see more than the limit number of items due to ReadListFilter. Note: This test uses raw websocket to verify patch protocol and limit enforcement
Types ¶
type ApplyObject ¶
type ApplyObject = filters.ApplyObject
Re-export filter types from filters package
type EndpointConfig ¶
type EndpointConfig struct {
Path string
Methods Methods
Description string
Vars Vars // Route variables like {id} - mandatory, auto-extracted from path if nil
Handler http.HandlerFunc
}
EndpointConfig configures a custom endpoint
type FetchResult ¶
FetchResult holds the result of a fetch operation for initial WebSocket message
type LimitFilterConfig ¶
type LimitFilterConfig = filters.LimitFilterConfig
LimitFilterConfig is an alias for filters.LimitFilterConfig for convenience. Use this with LimitFilter to configure limit and sort order.
type LimitFunc ¶
LimitFunc is an alias for filters.LimitFunc for convenience. Use this to provide a dynamic limit function that is called each time the limit is needed.
type MethodSpec ¶
type MethodSpec struct {
Request any // Go type for request body, nil for GET/DELETE
Response any // Go type for response body, nil if status-only
Params Params // Query parameters like ?category=x - optional
}
MethodSpec defines the specification for an HTTP method
type Server ¶
type Server struct {
Name string
Router *mux.Router
Stream stream.Stream
NoBroadcastKeys []string
Audit audit
Workers int
ForcePatch bool
NoPatch bool
OnSubscribe stream.Subscribe
OnUnsubscribe stream.Unsubscribe
OnStart func()
OnClose func()
Deadline time.Duration
AllowedOrigins []string
AllowedMethods []string
AllowedHeaders []string
ExposedHeaders []string
Storage storage.Database
Address string
Silence bool
Static bool
Tick time.Duration
Console *coat.Console
Signal chan os.Signal
Client *http.Client
ReadTimeout time.Duration
WriteTimeout time.Duration
ReadHeaderTimeout time.Duration
IdleTimeout time.Duration
OnStorageEvent storage.EventCallback
BeforeRead func(key string)
GetPivotInfo func() *ui.PivotInfo // Optional: returns pivot status for UI
// contains filtered or unexported fields
}
Server is the main application struct for the ooo server.
Name: display name for the server, shown in the storage explorer title
Router: can be predefined with routes and passed to be extended
Stream: manages WebSocket connections and broadcasts
NoBroadcastKeys: array of keys that should not broadcast on changes
Audit: function to audit requests, returns true to approve, false to deny
Workers: number of workers to use as readers of the storage->broadcast channel
ForcePatch: flag to force patch operations even if the patch is bigger than the snapshot
NoPatch: flag to disable patch operations entirely, always send full snapshots
OnSubscribe: function to monitor subscribe events, can return error to deny subscription
OnUnsubscribe: function to monitor unsubscribe events
OnStart: function that triggers after the server has started successfully
OnClose: function that triggers after closing the application
Deadline: time duration of a request before timing out
AllowedOrigins: list of allowed origins for cross domain access, defaults to ["*"]
AllowedMethods: list of allowed methods for cross domain access, defaults to ["GET", "POST", "DELETE", "PUT", "PATCH"]
AllowedHeaders: list of allowed headers for cross domain access, defaults to ["Authorization", "Content-Type"]
ExposedHeaders: list of exposed headers for cross domain access, defaults to nil
Storage: database interface implementation
Address: the address the server is listening on (populated after Start)
Silence: output silence flag, suppresses console output when true
Static: static routing flag, when true only filtered routes are allowed
Tick: time interval between ticks on the clock websocket
Console: logging console for the server
Signal: os signal channel for graceful shutdown
Client: http client to make requests
ReadTimeout: maximum duration for reading the entire request
WriteTimeout: maximum duration before timing out writes of the response
ReadHeaderTimeout: amount of time allowed to read request headers
IdleTimeout: maximum amount of time to wait for the next request
OnStorageEvent: callback function triggered on storage events
BeforeRead: callback function triggered before read operations
Example ¶
package main
import (
"github.com/benitogf/ooo"
)
func main() {
app := ooo.Server{}
app.Start("localhost:8800")
app.WaitClose()
}
func (*Server) AfterWriteFilter ¶
func (server *Server) AfterWriteFilter(path string, apply Notify, cfg ...FilterConfig)
AfterWriteFilter add a filter that triggers after a successful write
func (*Server) DeleteFilter ¶
func (server *Server) DeleteFilter(path string, apply Block, cfg ...FilterConfig)
DeleteFilter add a filter that runs before delete
func (*Server) Endpoint ¶
func (server *Server) Endpoint(cfg EndpointConfig)
Endpoint registers a custom HTTP endpoint with metadata for UI visibility
func (*Server) LimitFilter ¶
func (server *Server) LimitFilter(path string, cfg filters.LimitFilterConfig)
LimitFilter creates a limit filter for a glob pattern path that maintains a maximum number of entries. Uses a ReadListFilter (meta-based) to limit the view (so clients never see more than limit items) and AfterWrite to delete old entries. Also adds write and delete filters to allow creating and deleting items.
func (*Server) OpenFilter ¶
func (server *Server) OpenFilter(name string, cfg ...FilterConfig)
OpenFilter open noop read and write filters For glob paths like "things/*", this also enables reading individual items like "things/123"
func (*Server) ReadListFilter ¶
func (server *Server) ReadListFilter(path string, apply ApplyList, cfg ...FilterConfig)
ReadListFilter add a filter for []meta.Object reads. For glob paths like "things/*", individual item reads (e.g., "things/123") will also be allowed if no explicit ReadObjectFilter is registered for that path.
func (*Server) ReadObjectFilter ¶
func (server *Server) ReadObjectFilter(path string, apply ApplyObject, cfg ...FilterConfig)
ReadObjectFilter add a filter for single meta.Object reads
func (*Server) RegisterLimitFilter ¶
func (server *Server) RegisterLimitFilter(lf *filters.LimitFilter, description string, schema map[string]any)
RegisterLimitFilter registers a limit filter and tracks it for the ui. The LimitFilter should already be created and its filters added to the server. This method stores a reference to the filter for lazy evaluation of dynamic limits.
func (*Server) RegisterPreClose ¶
func (server *Server) RegisterPreClose(cleanup func())
RegisterPreClose registers a cleanup function to be called at the very start of Close(), before stream and storage cleanup. This is useful for stopping background goroutines that depend on the stream being active. Multiple functions can be registered and will be called in registration order.
func (*Server) RegisterProxy ¶
RegisterProxy registers a proxy route for UI visibility
func (*Server) RegisterProxyCleanup ¶
func (server *Server) RegisterProxyCleanup(cleanup func())
RegisterProxyCleanup registers a cleanup function to be called when the server closes. This is used by proxy routes to clean up their remote subscriptions.
func (*Server) Start ¶
Start initializes and starts the http server and database connection. Panics if startup fails. Use StartWithError for error handling. If the server is already active, this is a no-op (does not panic).
func (*Server) StartWithError ¶
StartWithError initializes and starts the http server and database connection. Returns an error if startup fails instead of calling log.Fatal.
func (*Server) Validate ¶
Validate checks the server configuration for common issues. Call this before Start() to catch configuration errors early.
func (*Server) WaitClose ¶
func (server *Server) WaitClose()
WaitClose : Blocks waiting for SIGINT, SIGTERM, SIGKILL, SIGHUP
func (*Server) WriteFilter ¶
func (server *Server) WriteFilter(path string, apply Apply, cfg ...FilterConfig)
WriteFilter add a filter that triggers on write
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
samples
|
|
|
01_basic_server
command
Package main demonstrates a basic ooo server setup.
|
Package main demonstrates a basic ooo server setup. |
|
02_static_routes_filters_audit
command
Package main demonstrates static routes, filters, and audit middleware.
|
Package main demonstrates static routes, filters, and audit middleware. |
|
04_io_operations
command
Package main demonstrates I/O operations with typed helpers.
|
Package main demonstrates I/O operations with typed helpers. |
|
08_remote_io_operations
command
Package main demonstrates remote I/O operations.
|
Package main demonstrates remote I/O operations. |
|
09_custom_endpoints
command
Package main demonstrates custom HTTP endpoints with server.Endpoint().
|
Package main demonstrates custom HTTP endpoints with server.Endpoint(). |
|
12_limit_filter
command
Package main demonstrates the LimitFilter for capped collections.
|
Package main demonstrates the LimitFilter for capped collections. |
|
13_limit_filter_with_validation
command
Package main demonstrates LimitFilter with custom write validation.
|
Package main demonstrates LimitFilter with custom write validation. |
|
Build script for ooo website Generates the samples section from the samples directory
|
Build script for ooo website Generates the samples section from the samples directory |
|
preview
command
|
|