[{"data":1,"prerenderedAt":2024},["ShallowReactive",2],{"navigation_docs_en":3,"-en-storage-local":441,"-en-storage-local-surround":2019},[4,45,60,81,112,129,146,173,197,213,242,279,356,372,384,403,429],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"queue","i-lucide-layers","\u002Fen\u002Fqueue","en\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Overview","\u002Fen\u002Fqueue\u002Foverview","en\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F11.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F12.auth\u002F5.social-standalone","i-lucide-log-in",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fen\u002Fstorage\u002Foverview","en\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"Kit","i-lucide-box","\u002Fen\u002Fkit","en\u002F3.kit",[248,251,256,261,266,270,275],{"title":52,"path":249,"stem":250,"icon":244},"\u002Fen\u002Fkit\u002Foverview","en\u002F3.kit\u002F1.overview",{"title":252,"path":253,"stem":254,"icon":255},"Application lifecycle","\u002Fen\u002Fkit\u002Fapp","en\u002F3.kit\u002F2.app","i-lucide-power",{"title":257,"path":258,"stem":259,"icon":260},"Server","\u002Fen\u002Fkit\u002Fserver","en\u002F3.kit\u002F3.server","i-lucide-server",{"title":262,"path":263,"stem":264,"icon":265},"Worker","\u002Fen\u002Fkit\u002Fworker","en\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":267,"path":268,"stem":269,"icon":70},"Realtime","\u002Fen\u002Fkit\u002Frealtime","en\u002F3.kit\u002F5.realtime",{"title":271,"path":272,"stem":273,"icon":274},"Migrations","\u002Fen\u002Fkit\u002Fmigrations","en\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":276,"path":277,"stem":278,"icon":111},"Social login","\u002Fen\u002Fkit\u002Fsocial-login","en\u002F3.kit\u002F7.social-login",{"title":280,"icon":281,"path":282,"stem":283,"children":284,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F4.cli",[285,288,293,298,303,308,313,318,323,328,333,337,342,347,351],{"title":52,"path":286,"stem":287,"icon":281},"\u002Fen\u002Fcli\u002Foverview","en\u002F4.cli\u002F1.overview",{"title":289,"path":290,"stem":291,"icon":292},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":294,"path":295,"stem":296,"icon":297},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":299,"path":300,"stem":301,"icon":302},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":304,"path":305,"stem":306,"icon":307},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":309,"path":310,"stem":311,"icon":312},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":314,"path":315,"stem":316,"icon":317},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":319,"path":320,"stem":321,"icon":322},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":324,"path":325,"stem":326,"icon":327},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":329,"path":330,"stem":331,"icon":332},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":334,"path":335,"stem":336,"icon":244},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F4.cli\u002F5.add-core",{"title":338,"path":339,"stem":340,"icon":341},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":343,"path":344,"stem":345,"icon":346},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":348,"path":349,"stem":350,"icon":265},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F4.cli\u002F8.worker-generators",{"title":352,"path":353,"stem":354,"icon":355},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":357,"icon":227,"path":358,"stem":359,"children":360,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F5.errs",[361,364,368],{"title":52,"path":362,"stem":363,"icon":227},"\u002Fen\u002Ferrs\u002Foverview","en\u002F5.errs\u002F1.overview",{"title":365,"path":366,"stem":367},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F5.errs\u002F2.api",{"title":369,"path":370,"stem":371,"icon":227},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F5.errs\u002F3.integration",{"title":373,"icon":231,"path":374,"stem":375,"children":376,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F6.envconf",[377,380],{"title":52,"path":378,"stem":379,"icon":231},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F6.envconf\u002F1.overview",{"title":381,"path":382,"stem":383},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F6.envconf\u002F2.recipes",{"title":385,"icon":386,"path":387,"stem":388,"children":389,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F7.httperr",[390,393,398],{"title":52,"path":391,"stem":392,"icon":386},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F7.httperr\u002F1.overview",{"title":394,"path":395,"stem":396,"icon":397},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":399,"path":400,"stem":401,"icon":402},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":404,"icon":405,"path":406,"stem":407,"children":408,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F8.dbx",[409,412,416,420,425],{"title":52,"path":410,"stem":411,"icon":405},"\u002Fen\u002Fdbx\u002Foverview","en\u002F8.dbx\u002F1.overview",{"title":413,"path":414,"stem":415,"icon":106},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F8.dbx\u002F2.pg",{"title":417,"path":418,"stem":419,"icon":47},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F8.dbx\u002F3.bunx",{"title":421,"path":422,"stem":423,"icon":424},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":426,"path":427,"stem":428,"icon":317},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F8.dbx\u002F5.seed",{"title":430,"icon":55,"path":431,"stem":432,"children":433,"page":44},"paginate","\u002Fen\u002Fpaginate","en\u002F9.paginate",[434,437],{"title":52,"path":435,"stem":436,"icon":55},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F9.paginate\u002F1.overview",{"title":438,"path":439,"stem":440,"icon":19},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F9.paginate\u002F2.cursor",{"id":442,"title":160,"body":443,"description":2012,"extension":2013,"links":2014,"meta":2015,"navigation":2016,"path":161,"seo":2017,"stem":162,"__hash__":2018},"docs_en\u002Fen\u002F15.storage\u002F3.local.md",{"type":444,"value":445,"toc":2004},"minimark",[446,478,483,622,641,933,945,949,1127,1208,1213,1229,1299,1316,1320,1970,1974,2000],[447,448,449,450,454,455,457,458,461,462,465,466,468,469,473,474,477],"p",{},"Two ",[451,452,453],"code",{},"Driver"," implementations ship inside the root ",[451,456,147],{}," module, no extra dependency beyond it: ",[451,459,460],{},"storage\u002Fmemory",", an in-process fake for tests, and ",[451,463,464],{},"storage\u002Flocal",", a filesystem-backed driver good enough for a single-server deployment or local development. Both satisfy the same ",[451,467,453],{}," contract as the ",[470,471,472],"a",{"href":165},"S3-compatible driver",", so code written against ",[451,475,476],{},"Disk"," doesn't change when you swap between them.",[479,480,482],"h2",{"id":481},"storagememory-for-tests","storage\u002Fmemory: for tests",[484,485,490],"pre",{"className":486,"code":487,"language":488,"meta":489,"style":489},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import \"github.com\u002Fgp-system\u002Fstorage\u002Fmemory\"\n\ndriver := memory.New()\ndriver := memory.New(memory.WithBaseURL(\"https:\u002F\u002Fcdn.test\"))\ndisk := storage.NewDisk(driver, storage.WithName(\"test\"))\n","go","",[451,491,492,512,519,542,580],{"__ignoreMap":489},[493,494,497,501,505,509],"span",{"class":495,"line":496},"line",1,[493,498,500],{"class":499},"s7zQu","import",[493,502,504],{"class":503},"sMK4o"," \"",[493,506,508],{"class":507},"sBMFI","github.com\u002Fgp-system\u002Fstorage\u002Fmemory",[493,510,511],{"class":503},"\"\n",[493,513,515],{"class":495,"line":514},2,[493,516,518],{"emptyLinePlaceholder":517},true,"\n",[493,520,522,526,529,532,535,539],{"class":495,"line":521},3,[493,523,525],{"class":524},"sTEyZ","driver ",[493,527,528],{"class":503},":=",[493,530,531],{"class":524}," memory",[493,533,534],{"class":503},".",[493,536,538],{"class":537},"s2Zo4","New",[493,540,541],{"class":503},"()\n",[493,543,545,547,549,551,553,555,558,561,563,566,568,571,575,577],{"class":495,"line":544},4,[493,546,525],{"class":524},[493,548,528],{"class":503},[493,550,531],{"class":524},[493,552,534],{"class":503},[493,554,538],{"class":537},[493,556,557],{"class":503},"(",[493,559,560],{"class":524},"memory",[493,562,534],{"class":503},[493,564,565],{"class":537},"WithBaseURL",[493,567,557],{"class":503},[493,569,570],{"class":503},"\"",[493,572,574],{"class":573},"sfazB","https:\u002F\u002Fcdn.test",[493,576,570],{"class":503},[493,578,579],{"class":503},"))\n",[493,581,583,586,588,591,593,596,598,601,604,606,608,611,613,615,618,620],{"class":495,"line":582},5,[493,584,585],{"class":524},"disk ",[493,587,528],{"class":503},[493,589,590],{"class":524}," storage",[493,592,534],{"class":503},[493,594,595],{"class":537},"NewDisk",[493,597,557],{"class":503},[493,599,600],{"class":524},"driver",[493,602,603],{"class":503},",",[493,605,590],{"class":524},[493,607,534],{"class":503},[493,609,610],{"class":537},"WithName",[493,612,557],{"class":503},[493,614,570],{"class":503},[493,616,617],{"class":573},"test",[493,619,570],{"class":503},[493,621,579],{"class":503},[447,623,624,627,628,630,631,633,634,637,638,640],{},[451,625,626],{},"memory.New"," returns a ",[451,629,453],{}," backed by an in-process map: no filesystem, no network, no container. ",[451,632,565],{}," sets the base that ",[451,635,636],{},"URL"," builds links from (default: an internal placeholder scheme); without it, ",[451,639,636],{}," still works, it just won't look like a real link. This is the driver of choice for a service-layer unit test:",[484,642,644],{"className":486,"code":643,"language":488,"meta":489,"style":489},"func TestUploadStoresImageAndURL(t *testing.T) {\n    disk := storage.NewDisk(memory.New(memory.WithBaseURL(\"https:\u002F\u002Fcdn.test\")))\n    svc := service.NewProductImageService(disk, repo)\n\n    url, err := svc.Upload(ctx, \"p42\", strings.NewReader(\"png-bytes\"), storage.PutOptions{ContentType: \"image\u002Fpng\"})\n\n    require.NoError(t, err)\n    require.Equal(t, \"https:\u002F\u002Fcdn.test\u002Fproducts\u002Fp42\u002Fimage\", url)\n    require.True(t, disk.Exists(ctx, \"products\u002Fp42\u002Fimage\"))\n}\n",[451,645,646,677,717,745,749,831,836,858,888,927],{"__ignoreMap":489},[493,647,648,651,654,656,660,663,666,668,671,674],{"class":495,"line":496},[493,649,650],{"class":503},"func",[493,652,653],{"class":537}," TestUploadStoresImageAndURL",[493,655,557],{"class":503},[493,657,659],{"class":658},"sHdIc","t",[493,661,662],{"class":503}," *",[493,664,665],{"class":507},"testing",[493,667,534],{"class":503},[493,669,670],{"class":507},"T",[493,672,673],{"class":503},")",[493,675,676],{"class":503}," {\n",[493,678,679,682,684,686,688,690,692,694,696,698,700,702,704,706,708,710,712,714],{"class":495,"line":514},[493,680,681],{"class":524},"    disk ",[493,683,528],{"class":503},[493,685,590],{"class":524},[493,687,534],{"class":503},[493,689,595],{"class":537},[493,691,557],{"class":503},[493,693,560],{"class":524},[493,695,534],{"class":503},[493,697,538],{"class":537},[493,699,557],{"class":503},[493,701,560],{"class":524},[493,703,534],{"class":503},[493,705,565],{"class":537},[493,707,557],{"class":503},[493,709,570],{"class":503},[493,711,574],{"class":573},[493,713,570],{"class":503},[493,715,716],{"class":503},")))\n",[493,718,719,722,724,727,729,732,734,737,739,742],{"class":495,"line":521},[493,720,721],{"class":524},"    svc ",[493,723,528],{"class":503},[493,725,726],{"class":524}," service",[493,728,534],{"class":503},[493,730,731],{"class":537},"NewProductImageService",[493,733,557],{"class":503},[493,735,736],{"class":524},"disk",[493,738,603],{"class":503},[493,740,741],{"class":524}," repo",[493,743,744],{"class":503},")\n",[493,746,747],{"class":495,"line":544},[493,748,518],{"emptyLinePlaceholder":517},[493,750,751,754,756,759,761,764,766,769,771,774,776,778,781,783,785,788,790,793,795,797,800,802,805,807,809,812,815,818,821,823,826,828],{"class":495,"line":582},[493,752,753],{"class":524},"    url",[493,755,603],{"class":503},[493,757,758],{"class":524}," err ",[493,760,528],{"class":503},[493,762,763],{"class":524}," svc",[493,765,534],{"class":503},[493,767,768],{"class":537},"Upload",[493,770,557],{"class":503},[493,772,773],{"class":524},"ctx",[493,775,603],{"class":503},[493,777,504],{"class":503},[493,779,780],{"class":573},"p42",[493,782,570],{"class":503},[493,784,603],{"class":503},[493,786,787],{"class":524}," strings",[493,789,534],{"class":503},[493,791,792],{"class":537},"NewReader",[493,794,557],{"class":503},[493,796,570],{"class":503},[493,798,799],{"class":573},"png-bytes",[493,801,570],{"class":503},[493,803,804],{"class":503},"),",[493,806,590],{"class":507},[493,808,534],{"class":503},[493,810,811],{"class":507},"PutOptions",[493,813,814],{"class":503},"{",[493,816,817],{"class":524},"ContentType",[493,819,820],{"class":503},":",[493,822,504],{"class":503},[493,824,825],{"class":573},"image\u002Fpng",[493,827,570],{"class":503},[493,829,830],{"class":503},"})\n",[493,832,834],{"class":495,"line":833},6,[493,835,518],{"emptyLinePlaceholder":517},[493,837,839,842,844,847,849,851,853,856],{"class":495,"line":838},7,[493,840,841],{"class":524},"    require",[493,843,534],{"class":503},[493,845,846],{"class":537},"NoError",[493,848,557],{"class":503},[493,850,659],{"class":524},[493,852,603],{"class":503},[493,854,855],{"class":524}," err",[493,857,744],{"class":503},[493,859,861,863,865,868,870,872,874,876,879,881,883,886],{"class":495,"line":860},8,[493,862,841],{"class":524},[493,864,534],{"class":503},[493,866,867],{"class":537},"Equal",[493,869,557],{"class":503},[493,871,659],{"class":524},[493,873,603],{"class":503},[493,875,504],{"class":503},[493,877,878],{"class":573},"https:\u002F\u002Fcdn.test\u002Fproducts\u002Fp42\u002Fimage",[493,880,570],{"class":503},[493,882,603],{"class":503},[493,884,885],{"class":524}," url",[493,887,744],{"class":503},[493,889,891,893,895,898,900,902,904,907,909,912,914,916,918,920,923,925],{"class":495,"line":890},9,[493,892,841],{"class":524},[493,894,534],{"class":503},[493,896,897],{"class":537},"True",[493,899,557],{"class":503},[493,901,659],{"class":524},[493,903,603],{"class":503},[493,905,906],{"class":524}," disk",[493,908,534],{"class":503},[493,910,911],{"class":537},"Exists",[493,913,557],{"class":503},[493,915,773],{"class":524},[493,917,603],{"class":503},[493,919,504],{"class":503},[493,921,922],{"class":573},"products\u002Fp42\u002Fimage",[493,924,570],{"class":503},[493,926,579],{"class":503},[493,928,930],{"class":495,"line":929},10,[493,931,932],{"class":503},"}\n",[447,934,935,936,938,939,944],{},"If you're writing a ",[451,937,453],{}," of your own rather than using either of these two, run it through ",[470,940,941],{"href":170},[451,942,943],{},"storage\u002Fstoragetest"," to confirm it behaves the same way.",[479,946,948],{"id":947},"storagelocal-filesystem-backed-with-signed-urls","storage\u002Flocal: filesystem-backed, with signed URLs",[484,950,952],{"className":486,"code":951,"language":488,"meta":489,"style":489},"import \"github.com\u002Fgp-system\u002Fstorage\u002Flocal\"\n\ncfg := local.Config{\n    Root:          \"\u002Fvar\u002Fdata\u002Fuploads\",\n    PublicBaseURL: \"https:\u002F\u002Fcdn.example.com\",\n    BaseURL:       \"https:\u002F\u002Fapi.example.com\u002Ffiles\",\n    Secret:        os.Getenv(\"STORAGE_LOCAL_SECRET\"),\n}\ndriver, err := local.New(cfg)\ndisk := storage.NewDisk(driver, storage.WithName(\"uploads\"))\n",[451,953,954,965,969,987,1005,1021,1038,1065,1069,1092],{"__ignoreMap":489},[493,955,956,958,960,963],{"class":495,"line":496},[493,957,500],{"class":499},[493,959,504],{"class":503},[493,961,962],{"class":507},"github.com\u002Fgp-system\u002Fstorage\u002Flocal",[493,964,511],{"class":503},[493,966,967],{"class":495,"line":514},[493,968,518],{"emptyLinePlaceholder":517},[493,970,971,974,976,979,981,984],{"class":495,"line":521},[493,972,973],{"class":524},"cfg ",[493,975,528],{"class":503},[493,977,978],{"class":507}," local",[493,980,534],{"class":503},[493,982,983],{"class":507},"Config",[493,985,986],{"class":503},"{\n",[493,988,989,992,994,997,1000,1002],{"class":495,"line":544},[493,990,991],{"class":524},"    Root",[493,993,820],{"class":503},[493,995,996],{"class":503},"          \"",[493,998,999],{"class":573},"\u002Fvar\u002Fdata\u002Fuploads",[493,1001,570],{"class":503},[493,1003,1004],{"class":503},",\n",[493,1006,1007,1010,1012,1014,1017,1019],{"class":495,"line":582},[493,1008,1009],{"class":524},"    PublicBaseURL",[493,1011,820],{"class":503},[493,1013,504],{"class":503},[493,1015,1016],{"class":573},"https:\u002F\u002Fcdn.example.com",[493,1018,570],{"class":503},[493,1020,1004],{"class":503},[493,1022,1023,1026,1028,1031,1034,1036],{"class":495,"line":833},[493,1024,1025],{"class":524},"    BaseURL",[493,1027,820],{"class":503},[493,1029,1030],{"class":503},"       \"",[493,1032,1033],{"class":573},"https:\u002F\u002Fapi.example.com\u002Ffiles",[493,1035,570],{"class":503},[493,1037,1004],{"class":503},[493,1039,1040,1043,1045,1048,1050,1053,1055,1057,1060,1062],{"class":495,"line":838},[493,1041,1042],{"class":524},"    Secret",[493,1044,820],{"class":503},[493,1046,1047],{"class":524},"        os",[493,1049,534],{"class":503},[493,1051,1052],{"class":537},"Getenv",[493,1054,557],{"class":503},[493,1056,570],{"class":503},[493,1058,1059],{"class":573},"STORAGE_LOCAL_SECRET",[493,1061,570],{"class":503},[493,1063,1064],{"class":503},"),\n",[493,1066,1067],{"class":495,"line":860},[493,1068,932],{"class":503},[493,1070,1071,1073,1075,1077,1079,1081,1083,1085,1087,1090],{"class":495,"line":890},[493,1072,600],{"class":524},[493,1074,603],{"class":503},[493,1076,758],{"class":524},[493,1078,528],{"class":503},[493,1080,978],{"class":524},[493,1082,534],{"class":503},[493,1084,538],{"class":537},[493,1086,557],{"class":503},[493,1088,1089],{"class":524},"cfg",[493,1091,744],{"class":503},[493,1093,1094,1096,1098,1100,1102,1104,1106,1108,1110,1112,1114,1116,1118,1120,1123,1125],{"class":495,"line":929},[493,1095,585],{"class":524},[493,1097,528],{"class":503},[493,1099,590],{"class":524},[493,1101,534],{"class":503},[493,1103,595],{"class":537},[493,1105,557],{"class":503},[493,1107,600],{"class":524},[493,1109,603],{"class":503},[493,1111,590],{"class":524},[493,1113,534],{"class":503},[493,1115,610],{"class":537},[493,1117,557],{"class":503},[493,1119,570],{"class":503},[493,1121,1122],{"class":573},"uploads",[493,1124,570],{"class":503},[493,1126,579],{"class":503},[1128,1129,1130,1143],"table",{},[1131,1132,1133],"thead",{},[1134,1135,1136,1140],"tr",{},[1137,1138,1139],"th",{},"Field",[1137,1141,1142],{},"Meaning",[1144,1145,1146,1168,1185,1198],"tbody",{},[1134,1147,1148,1154],{},[1149,1150,1151],"td",{},[451,1152,1153],{},"Root",[1149,1155,1156,1157,1160,1161,1167],{},"the directory objects are read from and written to; every ",[451,1158,1159],{},"path"," is resolved under it, and ",[470,1162,1164],{"href":1163},"\u002Fen\u002Fstorage\u002Foverview#validpath",[451,1165,1166],{},"ValidPath"," rejects anything that would escape it",[1134,1169,1170,1175],{},[1149,1171,1172],{},[451,1173,1174],{},"PublicBaseURL",[1149,1176,1177,1178,1181,1182,1184],{},"base for ",[451,1179,1180],{},"Disk.URL",": a reverse proxy or CDN in front of ",[451,1183,1153],{},", if content is publicly served",[1134,1186,1187,1192],{},[1149,1188,1189],{},[451,1190,1191],{},"BaseURL",[1149,1193,1194,1195],{},"base URL the local driver's own signed links point at, i.e. where you mount its ",[451,1196,1197],{},"Handler",[1134,1199,1200,1205],{},[1149,1201,1202],{},[451,1203,1204],{},"Secret",[1149,1206,1207],{},"HMAC key signed URLs are generated and verified with",[1209,1210,1212],"h3",{"id":1211},"the-signed-url-handler","The signed-URL Handler",[447,1214,1215,1217,1218,1221,1222,1225,1226,1228],{},[451,1216,464],{}," doesn't just generate signed URLs, it also serves them: ",[451,1219,1220],{},"driver.Handler()"," returns an ",[451,1223,1224],{},"http.Handler"," you mount at the path implied by ",[451,1227,1191],{},", and it's what actually enforces the signature and expiry on incoming requests:",[484,1230,1232],{"className":486,"code":1231,"language":488,"meta":489,"style":489},"mux := http.NewServeMux()\nmux.Handle(\"\u002Ffiles\u002F\", http.StripPrefix(\"\u002Ffiles\u002F\", driver.Handler()))\n",[451,1233,1234,1251],{"__ignoreMap":489},[493,1235,1236,1239,1241,1244,1246,1249],{"class":495,"line":496},[493,1237,1238],{"class":524},"mux ",[493,1240,528],{"class":503},[493,1242,1243],{"class":524}," http",[493,1245,534],{"class":503},[493,1247,1248],{"class":537},"NewServeMux",[493,1250,541],{"class":503},[493,1252,1253,1256,1258,1261,1263,1265,1268,1270,1272,1274,1276,1279,1281,1283,1285,1287,1289,1292,1294,1296],{"class":495,"line":514},[493,1254,1255],{"class":524},"mux",[493,1257,534],{"class":503},[493,1259,1260],{"class":537},"Handle",[493,1262,557],{"class":503},[493,1264,570],{"class":503},[493,1266,1267],{"class":573},"\u002Ffiles\u002F",[493,1269,570],{"class":503},[493,1271,603],{"class":503},[493,1273,1243],{"class":524},[493,1275,534],{"class":503},[493,1277,1278],{"class":537},"StripPrefix",[493,1280,557],{"class":503},[493,1282,570],{"class":503},[493,1284,1267],{"class":573},[493,1286,570],{"class":503},[493,1288,603],{"class":503},[493,1290,1291],{"class":524}," driver",[493,1293,534],{"class":503},[493,1295,1197],{"class":537},[493,1297,1298],{"class":503},"()))\n",[447,1300,1301,1302,1305,1306,1309,1310,1312,1313,1315],{},"A request without a valid, unexpired signature is rejected before the filesystem is touched. This is what makes ",[451,1303,1304],{},"TemporaryURL","\u002F",[451,1307,1308],{},"TemporaryUploadURL"," meaningful on a driver that has no cloud infrastructure behind it: the HMAC signature (over the path, an expiry timestamp, and ",[451,1311,1204],{},") is the entire access-control mechanism, so treat ",[451,1314,1204],{}," like any other credential (an env variable, never committed) and rotate it if it leaks.",[479,1317,1319],{"id":1318},"standalone-example","Standalone example",[484,1321,1324],{"className":486,"code":1322,"filename":1323,"language":488,"meta":489,"style":489},"package main\n\nimport (\n    \"context\"\n    \"log\"\n    \"net\u002Fhttp\"\n    \"os\"\n    \"strings\"\n    \"time\"\n\n    \"github.com\u002Fgp-system\u002Fstorage\"\n    \"github.com\u002Fgp-system\u002Fstorage\u002Flocal\"\n)\n\nfunc main() {\n    driver, err := local.New(local.Config{\n        Root:          \".\u002Fdata\",\n        PublicBaseURL: \"http:\u002F\u002Flocalhost:8080\u002Ffiles\",\n        BaseURL:       \"http:\u002F\u002Flocalhost:8080\u002Ffiles\",\n        Secret:        os.Getenv(\"STORAGE_LOCAL_SECRET\"),\n    })\n    if err != nil {\n        log.Fatal(err)\n    }\n    disk := storage.NewDisk(driver, storage.WithName(\"local\"))\n\n    ctx := context.Background()\n    if err := disk.Put(ctx, \"hello.txt\", strings.NewReader(\"hello, disk\"), storage.PutOptions{}); err != nil {\n        log.Fatal(err)\n    }\n\n    signed, err := disk.TemporaryURL(ctx, \"hello.txt\", storage.TemporaryURLOptions{TTL: 5 * time.Minute})\n    if err != nil {\n        log.Fatal(err)\n    }\n    log.Println(\"signed link:\", signed)\n\n    mux := http.NewServeMux()\n    mux.Handle(\"\u002Ffiles\u002F\", http.StripPrefix(\"\u002Ffiles\u002F\", driver.Handler()))\n    log.Fatal(http.ListenAndServe(\":8080\", mux))\n}\n","main.go",[451,1325,1326,1334,1338,1345,1355,1364,1373,1382,1391,1400,1404,1414,1423,1428,1433,1446,1475,1492,1509,1525,1549,1555,1571,1589,1595,1630,1635,1653,1718,1733,1738,1743,1805,1818,1833,1838,1865,1870,1886,1930,1965],{"__ignoreMap":489},[493,1327,1328,1331],{"class":495,"line":496},[493,1329,1330],{"class":503},"package",[493,1332,1333],{"class":507}," main\n",[493,1335,1336],{"class":495,"line":514},[493,1337,518],{"emptyLinePlaceholder":517},[493,1339,1340,1342],{"class":495,"line":521},[493,1341,500],{"class":499},[493,1343,1344],{"class":503}," (\n",[493,1346,1347,1350,1353],{"class":495,"line":544},[493,1348,1349],{"class":503},"    \"",[493,1351,1352],{"class":507},"context",[493,1354,511],{"class":503},[493,1356,1357,1359,1362],{"class":495,"line":582},[493,1358,1349],{"class":503},[493,1360,1361],{"class":507},"log",[493,1363,511],{"class":503},[493,1365,1366,1368,1371],{"class":495,"line":833},[493,1367,1349],{"class":503},[493,1369,1370],{"class":507},"net\u002Fhttp",[493,1372,511],{"class":503},[493,1374,1375,1377,1380],{"class":495,"line":838},[493,1376,1349],{"class":503},[493,1378,1379],{"class":507},"os",[493,1381,511],{"class":503},[493,1383,1384,1386,1389],{"class":495,"line":860},[493,1385,1349],{"class":503},[493,1387,1388],{"class":507},"strings",[493,1390,511],{"class":503},[493,1392,1393,1395,1398],{"class":495,"line":890},[493,1394,1349],{"class":503},[493,1396,1397],{"class":507},"time",[493,1399,511],{"class":503},[493,1401,1402],{"class":495,"line":929},[493,1403,518],{"emptyLinePlaceholder":517},[493,1405,1407,1409,1412],{"class":495,"line":1406},11,[493,1408,1349],{"class":503},[493,1410,1411],{"class":507},"github.com\u002Fgp-system\u002Fstorage",[493,1413,511],{"class":503},[493,1415,1417,1419,1421],{"class":495,"line":1416},12,[493,1418,1349],{"class":503},[493,1420,962],{"class":507},[493,1422,511],{"class":503},[493,1424,1426],{"class":495,"line":1425},13,[493,1427,744],{"class":503},[493,1429,1431],{"class":495,"line":1430},14,[493,1432,518],{"emptyLinePlaceholder":517},[493,1434,1436,1438,1441,1444],{"class":495,"line":1435},15,[493,1437,650],{"class":503},[493,1439,1440],{"class":537}," main",[493,1442,1443],{"class":503},"()",[493,1445,676],{"class":503},[493,1447,1449,1452,1454,1456,1458,1460,1462,1464,1466,1469,1471,1473],{"class":495,"line":1448},16,[493,1450,1451],{"class":524},"    driver",[493,1453,603],{"class":503},[493,1455,758],{"class":524},[493,1457,528],{"class":503},[493,1459,978],{"class":524},[493,1461,534],{"class":503},[493,1463,538],{"class":537},[493,1465,557],{"class":503},[493,1467,1468],{"class":507},"local",[493,1470,534],{"class":503},[493,1472,983],{"class":507},[493,1474,986],{"class":503},[493,1476,1478,1481,1483,1485,1488,1490],{"class":495,"line":1477},17,[493,1479,1480],{"class":524},"        Root",[493,1482,820],{"class":503},[493,1484,996],{"class":503},[493,1486,1487],{"class":573},".\u002Fdata",[493,1489,570],{"class":503},[493,1491,1004],{"class":503},[493,1493,1495,1498,1500,1502,1505,1507],{"class":495,"line":1494},18,[493,1496,1497],{"class":524},"        PublicBaseURL",[493,1499,820],{"class":503},[493,1501,504],{"class":503},[493,1503,1504],{"class":573},"http:\u002F\u002Flocalhost:8080\u002Ffiles",[493,1506,570],{"class":503},[493,1508,1004],{"class":503},[493,1510,1512,1515,1517,1519,1521,1523],{"class":495,"line":1511},19,[493,1513,1514],{"class":524},"        BaseURL",[493,1516,820],{"class":503},[493,1518,1030],{"class":503},[493,1520,1504],{"class":573},[493,1522,570],{"class":503},[493,1524,1004],{"class":503},[493,1526,1528,1531,1533,1535,1537,1539,1541,1543,1545,1547],{"class":495,"line":1527},20,[493,1529,1530],{"class":524},"        Secret",[493,1532,820],{"class":503},[493,1534,1047],{"class":524},[493,1536,534],{"class":503},[493,1538,1052],{"class":537},[493,1540,557],{"class":503},[493,1542,570],{"class":503},[493,1544,1059],{"class":573},[493,1546,570],{"class":503},[493,1548,1064],{"class":503},[493,1550,1552],{"class":495,"line":1551},21,[493,1553,1554],{"class":503},"    })\n",[493,1556,1558,1561,1563,1566,1569],{"class":495,"line":1557},22,[493,1559,1560],{"class":499},"    if",[493,1562,758],{"class":524},[493,1564,1565],{"class":503},"!=",[493,1567,1568],{"class":503}," nil",[493,1570,676],{"class":503},[493,1572,1574,1577,1579,1582,1584,1587],{"class":495,"line":1573},23,[493,1575,1576],{"class":524},"        log",[493,1578,534],{"class":503},[493,1580,1581],{"class":537},"Fatal",[493,1583,557],{"class":503},[493,1585,1586],{"class":524},"err",[493,1588,744],{"class":503},[493,1590,1592],{"class":495,"line":1591},24,[493,1593,1594],{"class":503},"    }\n",[493,1596,1598,1600,1602,1604,1606,1608,1610,1612,1614,1616,1618,1620,1622,1624,1626,1628],{"class":495,"line":1597},25,[493,1599,681],{"class":524},[493,1601,528],{"class":503},[493,1603,590],{"class":524},[493,1605,534],{"class":503},[493,1607,595],{"class":537},[493,1609,557],{"class":503},[493,1611,600],{"class":524},[493,1613,603],{"class":503},[493,1615,590],{"class":524},[493,1617,534],{"class":503},[493,1619,610],{"class":537},[493,1621,557],{"class":503},[493,1623,570],{"class":503},[493,1625,1468],{"class":573},[493,1627,570],{"class":503},[493,1629,579],{"class":503},[493,1631,1633],{"class":495,"line":1632},26,[493,1634,518],{"emptyLinePlaceholder":517},[493,1636,1638,1641,1643,1646,1648,1651],{"class":495,"line":1637},27,[493,1639,1640],{"class":524},"    ctx ",[493,1642,528],{"class":503},[493,1644,1645],{"class":524}," context",[493,1647,534],{"class":503},[493,1649,1650],{"class":537},"Background",[493,1652,541],{"class":503},[493,1654,1656,1658,1660,1662,1664,1666,1669,1671,1673,1675,1677,1680,1682,1684,1686,1688,1690,1692,1694,1697,1699,1701,1703,1705,1707,1710,1712,1714,1716],{"class":495,"line":1655},28,[493,1657,1560],{"class":499},[493,1659,758],{"class":524},[493,1661,528],{"class":503},[493,1663,906],{"class":524},[493,1665,534],{"class":503},[493,1667,1668],{"class":537},"Put",[493,1670,557],{"class":503},[493,1672,773],{"class":524},[493,1674,603],{"class":503},[493,1676,504],{"class":503},[493,1678,1679],{"class":573},"hello.txt",[493,1681,570],{"class":503},[493,1683,603],{"class":503},[493,1685,787],{"class":524},[493,1687,534],{"class":503},[493,1689,792],{"class":537},[493,1691,557],{"class":503},[493,1693,570],{"class":503},[493,1695,1696],{"class":573},"hello, disk",[493,1698,570],{"class":503},[493,1700,804],{"class":503},[493,1702,590],{"class":507},[493,1704,534],{"class":503},[493,1706,811],{"class":507},[493,1708,1709],{"class":503},"{});",[493,1711,758],{"class":524},[493,1713,1565],{"class":503},[493,1715,1568],{"class":503},[493,1717,676],{"class":503},[493,1719,1721,1723,1725,1727,1729,1731],{"class":495,"line":1720},29,[493,1722,1576],{"class":524},[493,1724,534],{"class":503},[493,1726,1581],{"class":537},[493,1728,557],{"class":503},[493,1730,1586],{"class":524},[493,1732,744],{"class":503},[493,1734,1736],{"class":495,"line":1735},30,[493,1737,1594],{"class":503},[493,1739,1741],{"class":495,"line":1740},31,[493,1742,518],{"emptyLinePlaceholder":517},[493,1744,1746,1749,1751,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771,1773,1775,1777,1779,1782,1784,1787,1789,1793,1795,1798,1800,1803],{"class":495,"line":1745},32,[493,1747,1748],{"class":524},"    signed",[493,1750,603],{"class":503},[493,1752,758],{"class":524},[493,1754,528],{"class":503},[493,1756,906],{"class":524},[493,1758,534],{"class":503},[493,1760,1304],{"class":537},[493,1762,557],{"class":503},[493,1764,773],{"class":524},[493,1766,603],{"class":503},[493,1768,504],{"class":503},[493,1770,1679],{"class":573},[493,1772,570],{"class":503},[493,1774,603],{"class":503},[493,1776,590],{"class":507},[493,1778,534],{"class":503},[493,1780,1781],{"class":507},"TemporaryURLOptions",[493,1783,814],{"class":503},[493,1785,1786],{"class":524},"TTL",[493,1788,820],{"class":503},[493,1790,1792],{"class":1791},"sbssI"," 5",[493,1794,662],{"class":503},[493,1796,1797],{"class":524}," time",[493,1799,534],{"class":503},[493,1801,1802],{"class":524},"Minute",[493,1804,830],{"class":503},[493,1806,1808,1810,1812,1814,1816],{"class":495,"line":1807},33,[493,1809,1560],{"class":499},[493,1811,758],{"class":524},[493,1813,1565],{"class":503},[493,1815,1568],{"class":503},[493,1817,676],{"class":503},[493,1819,1821,1823,1825,1827,1829,1831],{"class":495,"line":1820},34,[493,1822,1576],{"class":524},[493,1824,534],{"class":503},[493,1826,1581],{"class":537},[493,1828,557],{"class":503},[493,1830,1586],{"class":524},[493,1832,744],{"class":503},[493,1834,1836],{"class":495,"line":1835},35,[493,1837,1594],{"class":503},[493,1839,1841,1844,1846,1849,1851,1853,1856,1858,1860,1863],{"class":495,"line":1840},36,[493,1842,1843],{"class":524},"    log",[493,1845,534],{"class":503},[493,1847,1848],{"class":537},"Println",[493,1850,557],{"class":503},[493,1852,570],{"class":503},[493,1854,1855],{"class":573},"signed link:",[493,1857,570],{"class":503},[493,1859,603],{"class":503},[493,1861,1862],{"class":524}," signed",[493,1864,744],{"class":503},[493,1866,1868],{"class":495,"line":1867},37,[493,1869,518],{"emptyLinePlaceholder":517},[493,1871,1873,1876,1878,1880,1882,1884],{"class":495,"line":1872},38,[493,1874,1875],{"class":524},"    mux ",[493,1877,528],{"class":503},[493,1879,1243],{"class":524},[493,1881,534],{"class":503},[493,1883,1248],{"class":537},[493,1885,541],{"class":503},[493,1887,1889,1892,1894,1896,1898,1900,1902,1904,1906,1908,1910,1912,1914,1916,1918,1920,1922,1924,1926,1928],{"class":495,"line":1888},39,[493,1890,1891],{"class":524},"    mux",[493,1893,534],{"class":503},[493,1895,1260],{"class":537},[493,1897,557],{"class":503},[493,1899,570],{"class":503},[493,1901,1267],{"class":573},[493,1903,570],{"class":503},[493,1905,603],{"class":503},[493,1907,1243],{"class":524},[493,1909,534],{"class":503},[493,1911,1278],{"class":537},[493,1913,557],{"class":503},[493,1915,570],{"class":503},[493,1917,1267],{"class":573},[493,1919,570],{"class":503},[493,1921,603],{"class":503},[493,1923,1291],{"class":524},[493,1925,534],{"class":503},[493,1927,1197],{"class":537},[493,1929,1298],{"class":503},[493,1931,1933,1935,1937,1939,1941,1944,1946,1949,1951,1953,1956,1958,1960,1963],{"class":495,"line":1932},40,[493,1934,1843],{"class":524},[493,1936,534],{"class":503},[493,1938,1581],{"class":537},[493,1940,557],{"class":503},[493,1942,1943],{"class":524},"http",[493,1945,534],{"class":503},[493,1947,1948],{"class":537},"ListenAndServe",[493,1950,557],{"class":503},[493,1952,570],{"class":503},[493,1954,1955],{"class":573},":8080",[493,1957,570],{"class":503},[493,1959,603],{"class":503},[493,1961,1962],{"class":524}," mux",[493,1964,579],{"class":503},[493,1966,1968],{"class":495,"line":1967},41,[493,1969,932],{"class":503},[479,1971,1973],{"id":1972},"related-pages","Related pages",[1975,1976,1977,1983,1990,1995],"ul",{},[1978,1979,1980,1982],"li",{},[470,1981,52],{"href":153},": the Driver\u002FDisk\u002FManager model, and the decorators these drivers compose with.",[1978,1984,1985,1987,1988,534],{},[470,1986,156],{"href":157},": the full method set exposed through ",[451,1989,476],{},[1978,1991,1992,1994],{},[470,1993,164],{"href":165},": the driver to switch to for a production, multi-instance deployment.",[1978,1996,1997,1999],{},[470,1998,169],{"href":170},": the conformance suite both of these drivers pass.",[2001,2002,2003],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":489,"searchDepth":514,"depth":514,"links":2005},[2006,2007,2010,2011],{"id":481,"depth":514,"text":482},{"id":947,"depth":514,"text":948,"children":2008},[2009],{"id":1211,"depth":521,"text":1212},{"id":1318,"depth":514,"text":1319},{"id":1972,"depth":514,"text":1973},"The two drivers that ship in the root storage module, for tests and single-server deployments.","md",null,{},{"icon":148},{"title":160,"description":2012},"wrzoBcseT8SLxF5iGO9RgJVt7kA2j8DPj0rFJkPygfU",[2020,2022],{"title":156,"path":157,"stem":158,"description":2021,"children":-1},"[object Object]",{"title":164,"path":165,"stem":166,"description":2023,"icon":167,"children":-1},"The S3-compatible driver, a separately versioned module built on minio-go.",1785445902814]