Documentation
¶
Index ¶
- Constants
- Variables
- func AssetHandler() http.Handler
- func AssetsVersion() string
- func CacheHandler(hash string, next http.Handler) http.Handler
- func CreateUsernameFromBech32(username string) string
- func GetClientErrorStatusView(_ *weburl.GnoURL, err error, height int64) (int, *components.View)
- func NewDefaultChromaOptions() []chromahtml.Option
- func NewDefaultGoldmarkOptions() []goldmark.Option
- func NewRouter(logger *slog.Logger, cfg *AppConfig) (http.Handler, error)
- func NoCacheHandler(next http.Handler) http.Handler
- func RedirectMiddleware(next http.Handler, meta StaticMetadata) http.Handler
- type AliasKind
- type AliasTarget
- type AppConfig
- type ClientAdapter
- type CommunityIndex
- type FileMeta
- type HTMLRenderer
- func (r *HTMLRenderer) RenderDocumentation(w io.Writer, src []byte) error
- func (r *HTMLRenderer) RenderRealm(w io.Writer, u *weburl.GnoURL, src []byte, ctx RealmRenderContext) (md.RealmMeta, error)
- func (r *HTMLRenderer) RenderSource(w io.Writer, name string, src []byte) error
- func (r *HTMLRenderer) WriteChromaCSS(w io.Writer) error
- type HTTPHandler
- func (h *HTTPHandler) Get(w http.ResponseWriter, r *http.Request)
- func (h *HTTPHandler) GetDepsView(r *http.Request, gnourl *weburl.GnoURL) (int, *components.View)
- func (h *HTTPHandler) GetDirectoryView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, ...) (int, *components.View)
- func (h *HTTPHandler) GetHelpView(ctx context.Context, gnourl *weburl.GnoURL) (int, *components.View)
- func (h *HTTPHandler) GetMapView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData) (int, *components.View)
- func (h *HTTPHandler) GetMarkdownRealmView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, ...) (int, *components.View)
- func (h *HTTPHandler) GetMarkdownView(gnourl *weburl.GnoURL, alias AliasTarget, pr *pageRender) (int, *components.View)
- func (h *HTTPHandler) GetOverviewView(ctx context.Context, gnourl *weburl.GnoURL, pr *pageRender) (int, *components.View)
- func (h *HTTPHandler) GetPackageView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, ...) (int, *components.View)
- func (h *HTTPHandler) GetPathsListView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData) (int, *components.View)
- func (h *HTTPHandler) GetRealmView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, ...) (int, *components.View)
- func (h *HTTPHandler) GetSourceView(ctx context.Context, gnourl *weburl.GnoURL, pr *pageRender) (int, *components.View)
- func (h *HTTPHandler) GetUserView(ctx context.Context, gnourl *weburl.GnoURL, pr *pageRender) (int, *components.View)
- func (h *HTTPHandler) Post(w http.ResponseWriter, r *http.Request)
- func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (h *HTTPHandler) ServeHelpJSON(ctx context.Context, gnourl *weburl.GnoURL, w http.ResponseWriter)
- func (h *HTTPHandler) ServeSourceDownload(ctx context.Context, gnourl *weburl.GnoURL, w http.ResponseWriter, ...)
- type HTTPHandlerConfig
- type MockClient
- func (m *MockClient) Doc(ctx context.Context, path string, _ int64) (*doc.JSONDocumentation, error)
- func (m *MockClient) Eval(ctx context.Context, _, _ string) ([]byte, error)
- func (m *MockClient) File(ctx context.Context, pkgPath, fileName string, _ int64) ([]byte, FileMeta, error)
- func (m *MockClient) ListFiles(ctx context.Context, path string, _ int64) ([]string, error)
- func (m *MockClient) ListPaths(ctx context.Context, prefix string, limit int) ([]string, error)
- func (m *MockClient) PackageMeta(ctx context.Context, path string) (*vm.PackageMeta, error)
- func (m *MockClient) Realm(ctx context.Context, path, args string) ([]byte, error)
- func (m *MockClient) StateObject(_ context.Context, _ string, _ int64) ([]byte, error)
- func (m *MockClient) StatePkg(_ context.Context, path string, _ int64) ([]byte, error)
- func (m *MockClient) StateType(_ context.Context, _ string, _ int64) ([]byte, error)
- type MockPackage
- type PathsResult
- type RealmDirectory
- type RealmRenderContext
- type RenderConfig
- type Renderer
- type StaticMetadata
Constants ¶
const DefaultIPFSGateway = "https://ipfs.filebase.io"
DefaultIPFSGateway is the default of the gnoweb and gnodev gateway flags: the public gateway that ipfs:// URLs and URLs on the gateways in markdown's ipfsRewrittenGateways are rewritten to. See gno.land/adr/pr6270_gnoweb_ipfs_gateway.md for how it was chosen.
const DefaultTrustedPaths = "gnoland,sys,gov,nt,docs,demo,tests,gnops,devrels,moul,aeddi,aib,howl,leon,jeronimoalbi,mason,samcrew,onbloc,gnoswap"
DefaultTrustedPaths are the namespaces gno.land treats as official, comma separated as -trusted-paths takes them: namespaces whose code the gno.land team reviews or whose deploy key belongs to a party it vouches for (see the realm notice ADR). Trust in a namespace holds only on a chain that enforces who may deploy under it, as r/sys/names does once enabled.
const MaxUserContributions = 1000
MaxUserContributions caps how many contributions /u/<user> renders per namespace; a resolved user lists two. Each entry costs a weburl parse and a sort comparison; an unbounded cap turns a single GET into a 10k-iteration amplifier. It equals the node's own qpaths default, the cap this page always got before ListPaths forwarded its limit: lower would drop the tail of a large namespace and count what is left as the total. Exported so external tests assert against the documented cap. TODO: paginate via ?page= when a contributor exceeds this cap.
const ReadmeFileName = "README.md"
const RealmNoticeHeader = "X-Gnoweb-Realm-Notice"
RealmNoticeHeader is set to "community" on markdown responses of pages that show the realm notice, whose body is served verbatim.
const UserRegistryPath = "/r/sys/users"
UserRegistryPath is the realm that maps gno.land names to addresses, and the only source gnoweb has for either side of the pair.
Variables ¶
var ( ErrClientPackageNotFound = errors.New("package not found") ErrClientFileNotFound = errors.New("file not found") ErrClientObjectNotFound = errors.New("object not found") ErrClientRenderNotDeclared = errors.New("render function not declared") ErrClientBadRequest = errors.New("bad request") ErrClientTimeout = errors.New("RPC node request timeout") ErrClientResponse = errors.New("RPC node response error") ErrClientResponseTooLarge = errors.New("RPC node response too large") )
var DefaultAliases = map[string]AliasTarget{ "/": {Value: "/r/gnoland/home", Kind: GnowebPath}, "/about": {Value: "/r/gnoland/pages:p/about", Kind: GnowebPath}, "/gnolang": {Value: "/r/gnoland/pages:p/gnolang", Kind: GnowebPath}, "/ecosystem": {Value: "/r/gnoland/pages:p/ecosystem", Kind: GnowebPath}, "/start": {Value: "/r/gnoland/pages:p/start", Kind: GnowebPath}, "/license": {Value: "/r/gnoland/pages:p/license", Kind: GnowebPath}, "/contribute": {Value: "/r/gnoland/pages:p/contribute", Kind: GnowebPath}, "/links": {Value: "/r/gnoland/pages:p/links", Kind: GnowebPath}, "/events": {Value: "/r/devrels/events", Kind: GnowebPath}, "/partners": {Value: "/r/gnoland/pages:p/partners", Kind: GnowebPath}, "/docs": {Value: "/u/docs", Kind: GnowebPath}, }
var DefaultCacheAssetsHandler = func(next http.Handler) http.Handler { return CacheHandler(assetsHash, next) }
var DefaultChromaDarkRenderStyle = styles.Get("nord")
var DefaultChromaRenderStyle = styles.Get("friendly")
var Redirects = map[string]string{
"/blog": "/r/gnoland/blog",
"/gor": "/contribute",
"/game-of-realms": "/contribute",
"/grants": "/partners",
"/language": "/gnolang",
"/getting-started": "/start",
}
Redirects is a map of gnoweb paths that are redirected using RedirectMiddleware.
Functions ¶
func AssetHandler ¶
AssetHandler returns an http.Handler to serve static assets from the embedded filesystem. Assets are always served from the embedded /public directory.
func AssetsVersion ¶
func AssetsVersion() string
AssetsVersion returns the token stamped on asset URLs so a cache keyed on the URL refetches an asset once it changes. It is derived from the content of the embedded assets, so it is identical across restarts and across replicas running the same binary, and changes only when an asset changes.
func CacheHandler ¶
CacheHandler adds ETag and Cache-Control headers to all asset responses for caching.
func CreateUsernameFromBech32 ¶
CreateUsernameFromBech32 creates a shortened version of the username if it's a valid bech32 address.
func NewDefaultChromaOptions ¶
func NewDefaultChromaOptions() []chromahtml.Option
NewDefaultChromaOptions returns the default Chroma options for syntax highlighting.
func NewDefaultGoldmarkOptions ¶
NewDefaultGoldmarkOptions returns the default Goldmark options for Markdown rendering.
func NewRouter ¶
NewRouter initializes the gnoweb router with the specified logger and configuration. It sets up all routes, static asset handling, and middleware.
func NoCacheHandler ¶
NoCacheHandler always invalidates cache for all responses.
func RedirectMiddleware ¶
func RedirectMiddleware(next http.Handler, meta StaticMetadata) http.Handler
RedirectMiddleware redirects all incoming requests whose path matches any of the Redirects to the corresponding URL, and renders a redirect view.
Types ¶
type AliasTarget ¶
type AliasTarget struct {
Value string
Kind AliasKind
// Title and Description come from a static page's front matter, and are
// empty for every other alias.
Title string
Description string
}
func NewStaticAlias ¶
func NewStaticAlias(content string) AliasTarget
NewStaticAlias builds a static-markdown alias from a file's content, lifting an optional front matter block off the top:
--- title: About description: What gno.land is and why it exists. ---
It reads only the pages gnoweb is configured with, which the operator ships. Realm content never goes through it: a realm is permissionless, and metadata it could set without displaying it is the abuse #3910 warned about.
type AppConfig ¶
type AppConfig struct {
// UnsafeHTML, if enabled, allows to use HTML in the markdown.
UnsafeHTML bool
// Analytics enables SimpleAnalytics.
Analytics bool
// AnalyticsHostname, when non-empty, is rendered as data-hostname on the
// SimpleAnalytics script tag to override the hostname SA reports.
// Set this when the site listens on a host SA would otherwise report
// incorrectly (for example a non-default port in local development).
AnalyticsHostname string
// NodeRemote is the remote address of the gno.land node.
NodeRemote string
// NodeRequestTimeout define how much time a request to the remote node should live before timeout.
NodeRequestTimeout time.Duration
// RemoteHelp is the remote of the gno.land node, as used in the help page.
RemoteHelp string
// AssetsPath is the base path to the gnoweb assets.
AssetsPath string
// NoAssetsCache disables assets caching.
NoAssetsCache bool
// ChainID is the chain id, used for constructing the help page.
ChainID string
// FaucetURL, if specified, will be the URL to which `/faucet` redirects.
FaucetURL string
// Domain is the domain used by the node.
Domain string
// CanonicalOrigin is the public origin this deployment is reachable at,
// scheme included. Empty means no canonical tag: a canonical naming a host
// the visitor did not reach tells a crawler the content belongs elsewhere,
// and every deployment but one would be claiming gno.land's.
CanonicalOrigin string
// NoIndex keeps this deployment out of search engines (testnets, staging):
// every page is noindex, nofollow with no canonical, and no sitemap is
// served. Off by default, so a forgotten flag never drops a site from search.
NoIndex bool
// Banner, if set, displays a site-wide banner above the header.
Banner components.BannerData
// RealmNotice, if set, is shown as the header's second row on pages of
// packages outside TrustedPaths.
RealmNotice components.RealmNotice
// TrustedPaths are namespaces or package paths ("gnoland", "gnoswap/v1/pool";
// no "/r/" or "/p/" prefix), or "*" for every path, whose pages are official: they never show
// RealmNotice, may lend their own heading and summary to the page
// metadata, keep their internal links followed, and are indexed whatever
// IndexCommunity says.
TrustedPaths []string
// IndexCommunity says which pages outside TrustedPaths search engines may
// index; the others get noindex, nofollow and no canonical.
IndexCommunity CommunityIndex
// Aliases is a map of aliases pointing to another path or a static file.
Aliases map[string]AliasTarget
// RenderConfig defines the default configuration for rendering realms and source files.
RenderConfig RenderConfig
// StateRateLimitPerMinute caps the per-IP request rate against
// ?state* URLs and, in a separate bucket, $search (also used as the
// token-bucket burst). 0 ⇒ the HTTPHandler default (1200/min).
// ADR-003 §Resource bounds.
StateRateLimitPerMinute int
// StateRateLimitTrustedProxies is the list of trusted reverse-proxy
// CIDRs (or bare IPs) for the per-IP rate limiter. X-Real-IP is honored
// only for connections originating inside one of these networks, and so
// is X-Forwarded-Host for the page origin (shareable links, AI prompts);
// empty (the default) trusts nothing, so untrusted deployments never
// trust attacker-controlled headers. ADR-003 §Resource bounds.
StateRateLimitTrustedProxies []string
// IndexerURL, when non-empty, is the GraphQL endpoint of a tx-indexer
// gnoweb consults for search qualifiers the RPC node cannot answer
// (transactions, account activity, source-wide text search).
//
// Empty is the default and the whole feature switch: with no indexer,
// gnoweb makes no outbound request beyond its RPC node, and the
// qualifiers that would need one are not registered — they do not
// autocomplete and cannot be typed into a failing search. Indexer data is
// never consensus data and is labelled as such wherever it appears.
IndexerURL string
// IndexerToken, when set, is sent as a bearer credential to the indexer.
IndexerToken string
// MaxConcurrentRPC caps in-flight outbound RPCs per gnoweb instance
// against the chain node. 0 ⇒ the rpcClient default (32). Tighten on
// chain nodes under pressure; relax when capacity allows. ADR-003
// §Resource bounds.
MaxConcurrentRPC int
}
AppConfig contains configuration for gnoweb.
func NewDefaultAppConfig ¶
func NewDefaultAppConfig() *AppConfig
NewDefaultAppConfig returns a new default AppConfig. The default sets 127.0.0.1:26657 as the remote node, "dev" as the chain ID, and sets up assets to be served on /public/.
type ClientAdapter ¶
type ClientAdapter interface {
// Realm fetch the content of a realm from a given path and
// return the data.
Realm(ctx context.Context, path, args string) ([]byte, error) // raw Render() bytes
// File fetches the source file from a given package path and
// filename. `height = 0` queries the latest block; positive values
// pin the query to that historical height.
File(ctx context.Context, path, filename string, height int64) ([]byte, FileMeta, error)
// ListFiles lists all source files available in a specified
// package path. `height = 0` queries the latest block; non-zero
// pins the listing to a historical block.
ListFiles(ctx context.Context, path string, height int64) ([]string, error)
// QueryPath list any path given the specified prefix
ListPaths(ctx context.Context, prefix string, limit int) ([]string, error)
// Doc retrieves the JSON doc suitable for printing from a
// specified package path. `height = 0` queries the latest block;
// any positive value pins the query to that historical height.
Doc(ctx context.Context, path string, height int64) (*doc.JSONDocumentation, error)
// StatePkg retrieves the root state tree for a package. `height
// = 0` queries the latest block; positive values are forwarded
// to ABCI as-is.
StatePkg(ctx context.Context, path string, height int64) ([]byte, error)
// StateObject retrieves the children of an object by ObjectID at
// the given block height (0 for latest).
StateObject(ctx context.Context, oid string, height int64) ([]byte, error)
// StateType retrieves a type definition by TypeID at the given
// block height (0 for latest).
StateType(ctx context.Context, typeId string, height int64) ([]byte, error)
// PackageMeta reports whether a path holds a live package, one parked
// awaiting an approver, or nothing. An absent path is a nil error with
// status "absent", not ErrClientPackageNotFound: the caller needs to tell
// "nothing here" from "the node did not answer".
PackageMeta(ctx context.Context, path string) (*vm.PackageMeta, error)
// Eval evaluates a read-only Gno expression (`vm/qeval`) and returns the
// raw result, one line per return value. pkgPath carries no domain, since
// the client adds its own, and no dot: the node splits pkgPath from expr on
// the first dot after the first slash. expr is the caller's to keep safe.
Eval(ctx context.Context, pkgPath, expr string) ([]byte, error)
}
func NewRPCClientAdapter ¶
func NewRPCClientAdapter(logger *slog.Logger, cli *client.RPCClient, domain string, maxConcurrentRPC int) ClientAdapter
NewRPCClientAdapter creates a new instance of rpcClient. maxConcurrentRPC ≤ 0 ⇒ defaultMaxConcurrentRPC; positive values cap in-flight outbound RPCs at that count.
type CommunityIndex ¶
type CommunityIndex int
CommunityIndex says which community pages search engines may index, as set by -index-community. Official pages are always indexable.
const ( // IndexNoCommunity keeps every community page out of search results. It // is the zero value, so a handler configured without a choice fails // closed. IndexNoCommunity CommunityIndex = iota // IndexRegisteredCommunity indexes the bare page of a package or user // under a registered name, and no other community page. IndexRegisteredCommunity // IndexAllCommunity indexes community pages like official ones. IndexAllCommunity )
func (CommunityIndex) MarshalText ¶
func (c CommunityIndex) MarshalText() ([]byte, error)
MarshalText and UnmarshalText let the value be a flag.TextVar.
func (CommunityIndex) String ¶
func (c CommunityIndex) String() string
String is the -index-community value of c, the one table of names.
func (*CommunityIndex) UnmarshalText ¶
func (c *CommunityIndex) UnmarshalText(text []byte) error
type HTMLRenderer ¶
type HTMLRenderer struct {
// contains filtered or unexported fields
}
HTMLRenderer implements the Renderer interface for HTML output.
func NewHTMLRenderer ¶
func NewHTMLRenderer(logger *slog.Logger, cfg RenderConfig, client ClientAdapter) *HTMLRenderer
func (*HTMLRenderer) RenderDocumentation ¶
func (r *HTMLRenderer) RenderDocumentation(w io.Writer, src []byte) error
RenderDocumentation writes the HTML representation of doc-context markdown to w. HTML escaping is delegated to Goldmark.
func (*HTMLRenderer) RenderRealm ¶
func (r *HTMLRenderer) RenderRealm(w io.Writer, u *weburl.GnoURL, src []byte, ctx RealmRenderContext) (md.RealmMeta, error)
RenderRealm renders a realm to HTML and returns what the document says about itself: its table of contents, its heading and its summary.
func (*HTMLRenderer) RenderSource ¶
RenderSource renders a source file into HTML with syntax highlighting based on its extension.
func (*HTMLRenderer) WriteChromaCSS ¶
func (r *HTMLRenderer) WriteChromaCSS(w io.Writer) error
WriteChromaCSS writes the CSS for syntax highlighting to the provided writer. It outputs the light theme by default and, if configured, the dark theme scoped under [data-theme="dark"] using CSS nesting.
type HTTPHandler ¶
type HTTPHandler struct {
Logger *slog.Logger
Static StaticMetadata
Client ClientAdapter
Renderer Renderer
Aliases map[string]AliasTarget
Timeout time.Duration
// State is the feature/state handler that owns every ?state* URL.
// Built in NewHTTPHandler so the wire-in dispatch hook is a single
// method call (ADR-003 §Architecture).
State *state.Handler
// Search is the feature/omnisearch handler that owns every $search URL.
Search *omnisearch.Handler
// ChainMap is the feature/chainmap handler: the map of a listing, and the
// dependencies page with its importers.
ChainMap *chainmap.Handler
// contains filtered or unexported fields
}
HTTPHandler processes HTTP requests for gnoweb.
func NewHTTPHandler ¶
func NewHTTPHandler(logger *slog.Logger, cfg *HTTPHandlerConfig) (*HTTPHandler, error)
NewHTTPHandler creates a new HTTPHandler.
func (*HTTPHandler) Get ¶
func (h *HTTPHandler) Get(w http.ResponseWriter, r *http.Request)
Get processes a GET HTTP request and renders the appropriate page.
func (*HTTPHandler) GetDepsView ¶
func (h *HTTPHandler) GetDepsView(r *http.Request, gnourl *weburl.GnoURL) (int, *components.View)
GetDepsView renders a package's dependencies: what it imports, and what imports it. The answer costs an indexer scan per package, so Get keeps it from crawlers.
func (*HTTPHandler) GetDirectoryView ¶
func (h *HTTPHandler) GetDirectoryView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, pr *pageRender) (int, *components.View)
GetDirectoryView renders the directory view for a package, showing available files.
func (*HTTPHandler) GetHelpView ¶
func (h *HTTPHandler) GetHelpView(ctx context.Context, gnourl *weburl.GnoURL) (int, *components.View)
func (*HTTPHandler) GetMapView ¶
func (h *HTTPHandler) GetMapView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData) (int, *components.View)
GetMapView draws the listing below a path. A map exists only where the list does, which is where no package lives: on a package its Directory tab would open the package, not the listing. The same holds one level up, so the zoom-out link is offered only where the parent is not a package either. Both checks run beside the listing query.
func (*HTTPHandler) GetMarkdownRealmView ¶
func (h *HTTPHandler) GetMarkdownRealmView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, pr *pageRender) (int, *components.View)
GetMarkdownRealmView serves a realm's raw Render() output as text/markdown. It falls back to the directory, paths-list, or error view when the realm cannot be fetched.
func (*HTTPHandler) GetMarkdownView ¶
func (h *HTTPHandler) GetMarkdownView(gnourl *weburl.GnoURL, alias AliasTarget, pr *pageRender) (int, *components.View)
GetMarkdownView handles rendering of markdown files.
func (*HTTPHandler) GetOverviewView ¶
func (h *HTTPHandler) GetOverviewView(ctx context.Context, gnourl *weburl.GnoURL, pr *pageRender) (int, *components.View)
GetOverviewView renders the package overview landing page at /r/<pkg>$source. It fans out ListFiles, Doc, README and ListPaths in parallel, then builds a pure OverviewData that the template renders.
func (*HTTPHandler) GetPackageView ¶
func (h *HTTPHandler) GetPackageView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, pr *pageRender) (int, *components.View)
GetPackageView handles package pages, including help, source, directory, and user views.
func (*HTTPHandler) GetPathsListView ¶
func (h *HTTPHandler) GetPathsListView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData) (int, *components.View)
func (*HTTPHandler) GetRealmView ¶
func (h *HTTPHandler) GetRealmView(ctx context.Context, gnourl *weburl.GnoURL, indexData *components.IndexData, pr *pageRender) (int, *components.View)
GetRealmView renders a realm page as HTML, or returns an error/status if not available.
func (*HTTPHandler) GetSourceView ¶
func (h *HTTPHandler) GetSourceView(ctx context.Context, gnourl *weburl.GnoURL, pr *pageRender) (int, *components.View)
func (*HTTPHandler) GetUserView ¶
func (h *HTTPHandler) GetUserView(ctx context.Context, gnourl *weburl.GnoURL, pr *pageRender) (int, *components.View)
GetUserView returns the user profile view for a given GnoURL. The segment may be either half of the pair: /u/<name> and /u/<address> serve the same page, and each prints the other half. A page is served only for an address, a namespace holding packages, a current name r/sys/users resolves to itself, or a path this gnoweb's own aliases publish; anything else would be a fabricated profile.
func (*HTTPHandler) Post ¶
func (h *HTTPHandler) Post(w http.ResponseWriter, r *http.Request)
Post processes a POST HTTP request.
func (*HTTPHandler) ServeHTTP ¶
func (h *HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP handles HTTP requests and only allows GET requests.
func (*HTTPHandler) ServeHelpJSON ¶
func (h *HTTPHandler) ServeHelpJSON(ctx context.Context, gnourl *weburl.GnoURL, w http.ResponseWriter)
ServeHelpJSON serves the callable functions of a package as JSON.
func (*HTTPHandler) ServeSourceDownload ¶
func (h *HTTPHandler) ServeSourceDownload(ctx context.Context, gnourl *weburl.GnoURL, w http.ResponseWriter, r *http.Request)
ServeSourceDownload handles downloading a source file as plain text.
type HTTPHandlerConfig ¶
type HTTPHandlerConfig struct {
Meta StaticMetadata
ClientAdapter ClientAdapter
Renderer Renderer
Aliases map[string]AliasTarget
// TrustedPaths — see AppConfig field of the same name.
TrustedPaths []string
// IndexCommunity — see AppConfig field of the same name.
IndexCommunity CommunityIndex
Timeout time.Duration
// NoIndex — see AppConfig field of the same name.
NoIndex bool
// StateRateLimitPerMinute caps per-IP requests against ?state* URLs.
// 0 ⇒ defaultRateLimitPerMinute. Also used as the token-bucket
// burst. ADR-003 §Resource bounds.
StateRateLimitPerMinute int
// StateRateLimitTrustedProxies — see AppConfig field of the same name.
// Also gates X-Forwarded-Host in requestOrigin.
StateRateLimitTrustedProxies []string
// Directory lists realm and package paths for the search feature.
// Optional: callers that already have one — the router does, for
// /search.json — pass it so both share a singleflight group. Nil builds
// one here.
Directory RealmDirectory
// Indexer, when non-nil, enables the indexer-backed search qualifiers.
// Leave it nil, never a typed nil pointer: the interface is what
// feature/omnisearch tests to decide whether those qualifiers exist.
Indexer omnisearch.Indexer
}
HTTPHandlerConfig configures an HTTPHandler.
type MockClient ¶
type MockClient struct {
Packages map[string]*MockPackage // path -> package
}
MockClient is a mock implementation of the ClientAdapter interface for testing.
func NewMockClient ¶
func NewMockClient(pkgs ...*MockPackage) *MockClient
NewMockClient creates a new MockClient from one or more MockPackages.
func (*MockClient) Doc ¶
func (m *MockClient) Doc(ctx context.Context, path string, _ int64) (*doc.JSONDocumentation, error)
Doc retrieves the JSON documentation for a specified package path.
func (*MockClient) File ¶
func (m *MockClient) File(ctx context.Context, pkgPath, fileName string, _ int64) ([]byte, FileMeta, error)
File fetches the source file from a given package path and filename, returning its content and metadata.
func (*MockClient) ListFiles ¶
ListFiles lists all source files available in a specified package path.
func (*MockClient) ListPaths ¶
ListPaths lists all package paths that match the specified prefix, up to the given limit.
func (*MockClient) PackageMeta ¶
func (m *MockClient) PackageMeta(ctx context.Context, path string) (*vm.PackageMeta, error)
PackageMeta reports the mock's view of a path. A package present in the mock is live; Pending is set from MockPackage.Pending so a test can stage the parked case, which is the one gnoweb has to render differently.
func (*MockClient) Realm ¶
Realm fetches the content of a realm from a given path and returns the data, or an error if not found or not declared.
func (*MockClient) StateObject ¶
StateObject returns mock object state data for testing.
type MockPackage ¶
type MockPackage struct {
Path string
Domain string
Files map[string]string // filename -> body
Functions []*doc.JSONFunc
// Imports are what vm/qdoc reports the package imports.
Imports []string
// Inert stages a package that was submitted but not yet approved. The
// other methods still refuse it the way the chain does -- Render and the
// file queries read the live key space -- so a test gets the real shape.
Inert bool
// Pending stages a redeploy parked over a live package.
Pending bool
// Reason overrides the parked reason; defaults to awaiting-an-approver.
Reason string
}
MockPackage represents a mock package with files and function signatures for testing.
type PathsResult ¶
type PathsResult struct {
Realms []string
Packages []string
// Truncated reports that a listing came back at the cap, so the chain
// holds paths this result does not name. It is part of the answer: a
// silent cap is how a search comes to say "no such realm" about a realm
// that exists, and the lexicographic order of the underlying iterator
// means the paths dropped are always the same ones.
Truncated bool
}
PathsResult is a directory listing, plus whether the node capped it.
type RealmDirectory ¶
type RealmDirectory interface {
// Paths returns the realm (/r/) and package (/p/) paths known to the chain.
Paths(ctx context.Context) (PathsResult, error)
}
RealmDirectory exposes realm and package paths for discovery. It is the seam behind which the source can evolve (live RPC today, a dedicated search index later) without touching callers.
type RealmRenderContext ¶
type RealmRenderContext struct {
ChainId string
Remote string
Domain string
// Links says which links of the document search engines may follow.
Links md.LinkPolicy
}
RealmRenderContext holds context information for rendering realms
type RenderConfig ¶
type RenderConfig struct {
ChromaStyle *chroma.Style
ChromaDarkStyle *chroma.Style
ChromaOptions []chromahtml.Option
GoldmarkOptions []goldmark.Option
// IPFSGateway is the gateway origin, such as DefaultIPFSGateway, that
// ipfs:// URLs and URLs on the gateways in markdown's
// ipfsRewrittenGateways are rewritten to in realm markdown. Empty
// disables the rewrite. NewRouter rejects an invalid value;
// NewHTMLRenderer, which knows neither the chain domain nor the
// canonical origin, ignores a malformed one.
IPFSGateway string
}
RenderConfig holds configuration for syntax highlighting and Markdown rendering.
func NewDefaultRenderConfig ¶
func NewDefaultRenderConfig() (cfg RenderConfig)
NewDefaultRenderConfig returns a RenderConfig with default styles and options.
type Renderer ¶
type Renderer interface {
RenderRealm(w io.Writer, u *weburl.GnoURL, src []byte, ctx RealmRenderContext) (md.RealmMeta, error)
RenderSource(w io.Writer, name string, src []byte) error
// RenderDocumentation renders doc-context markdown (from vm/qdoc) to HTML.
// Fenced and indented code blocks are wrapped in collapsible <details>
// with Chroma highlighting. HTML escaping is delegated to Goldmark.
RenderDocumentation(w io.Writer, src []byte) error
}
Renderer defines the interface for rendering realms, source files, and doc-context markdown (function/type/package documentation).
type StaticMetadata ¶
type StaticMetadata struct {
Domain string
CanonicalOrigin string
AssetsPath string
ChromaPath string
RemoteHelp string
ChainId string
Analytics bool
AnalyticsHostname string
AssetsVersion string
Banner components.BannerData
RealmNotice components.RealmNotice
}
StaticMetadata holds static configuration for a web handler.
func (StaticMetadata) RedirectAnalytics ¶
func (s StaticMetadata) RedirectAnalytics() components.AnalyticsData
RedirectAnalytics builds the AnalyticsData for a redirect view. The redirect view is rendered outside IndexLayout, so the analytics fields must be populated explicitly rather than derived from HeadData.
Source Files
¶
- alias_static.go
- app.go
- cache.go
- canonical_origin.go
- client.go
- client_mock.go
- community_index.go
- counterpart.go
- crawl.go
- handler_http.go
- handler_map.go
- handler_search.go
- ipfs.go
- negotiate.go
- package_text.go
- page_kind.go
- realm_directory.go
- realm_notice.go
- redirect.go
- render.go
- render_config.go
- render_lexer.go
- static.go
- status.go
- trusted_paths.go