";let n=document.getElementById("TableOfContents");n&&(n.innerHTML=e)}rerender(){this.renderFilterMenu(),this.renderPageContent(),this.populateRightNav(),this.runHooks("afterRerender")}renderPageContent(){let e={};Object.keys(this.ifFunctionsByRef).forEach(t=>{let s=this.ifFunctionsByRef[t],o=s.value,n=(0,h.reresolveFunctionNode)(s,{variables:this.selectedValsByTraitId});this.ifFunctionsByRef[t]=n,o!==n.value&&(e[t]=n.value)});let t=document.getElementsByClassName("cdoc__toggleable");for(let n=0;n{this.fitCustomizationMenuToScreen()})}addDropdownEventListeners(){let e=document.getElementsByClassName("cdoc-dropdown");for(let t=0;t{let t=e.target;for(;!t.classList.contains("cdoc-dropdown")&&t.parentElement;)t=t.parentElement;let n=t.classList.toggle("cdoc-dropdown__expanded");t.setAttribute("aria-expanded",n.toString())});document.addEventListener("keydown",e=>{if(e.key==="Enter"){let t=e.target;t.classList.contains("cdoc-filter__option")&&t.click()}}),document.addEventListener("click",t=>{for(let n=0;nthis.handleFilterSelectionChange(e));this.addDropdownEventListeners()}locateFilterSelectorEl(){let e=document.getElementById("cdoc-selector");return!!e&&(this.filterSelectorEl=e,!0)}applyFilterSelectionOverrides(){let s=Object.keys(this.selectedValsByTraitId),e=!1,t=this.browserStorage.getTraitVals();Object.keys(t).forEach(n=>{s.includes(n)&&this.selectedValsByTraitId[n]!==t[n]&&(this.selectedValsByTraitId[n]=t[n],e=!0)});let n=(0,j.getTraitValsFromUrl)({url:new URL(window.location.href),traitIds:s});return Object.keys(n).forEach(t=>{this.selectedValsByTraitId[t]!==n[t]&&(this.selectedValsByTraitId[t]=n[t],e=!0)}),e}updateEditButton(){let t=document.getElementsByClassName("toc-edit-btn")[0];if(!t)return;let e=t.getElementsByTagName("a")[0];e&&(e.href=e.href.replace(/\.md\/$/,".mdoc.md/"))}revealPage(){this.runHooks("beforeReveal"),this.filterSelectorEl&&(this.filterSelectorEl.style.position="sticky",this.filterSelectorEl.style.backgroundColor="white",this.filterSelectorEl.style.paddingTop="10px",this.filterSelectorEl.style.visibility="visible",this.filterSelectorEl.style.zIndex="1000");let e=document.getElementById("cdoc-content");e&&(e.style.visibility="visible"),this.runHooks("afterReveal")}renderFilterMenu(){if(!this.filterSelectorEl||!this.filtersManifest)throw new Error("Cannot render filter selector without filtersManifest and filterSelectorEl");let e=(0,l.resolveFilters)({filtersManifest:this.filtersManifest,valsByTraitId:this.selectedValsByTraitId});Object.keys(e).forEach(t=>{let n=e[t];this.selectedValsByTraitId[t]=n.currentValue});let t=(0,y.buildCustomizationMenuUi)(e);this.filterSelectorEl.innerHTML=t,this.fitCustomizationMenuToScreen(),this.addFilterSelectorEventListeners()}fitCustomizationMenuToScreen(){let e=document.getElementById(g);if(!e)return;let s=e.classList.contains(n),t=document.getElementById(v);if(!t)throw new Error("Dropdown menu not found");let o=document.getElementById(b);if(!o)throw new Error("Menu wrapper not found");let i=e.scrollWidth>o.clientWidth;!s&&i?(e.classList.add(n),t.classList.remove(n)):s&&!i&&(e.classList.remove(n),t.classList.add(n))}get cdocsState(){return{selectedValsByTraitId:this.selectedValsByTraitId,ifFunctionsByRef:this.ifFunctionsByRef,filtersManifest:this.filtersManifest,browserStorage:this.browserStorage,filterSelectorEl:this.filterSelectorEl}}};e.ClientFiltersManager=r,t=r,s={value:void 0}}),y=e(e=>{Object.defineProperty(e,"__esModule",{value:!0});var t=j();window.clientFiltersManager=t.ClientFiltersManager.instance}),y()})()App and API Protection SDK for Go
This product is not supported for your selected Datadog site. ().
If you need flexibility and features beyond those available when instrumenting your application automatically using Orchestrion, Datadog provides an App and API Protection API located at github.com/DataDog/dd-trace-go/v2/appsec. This API improves flexibility and offers additional features.
Error event handling
The API error type events.BlockingSecurityEvent is returned when a blocking event occurs, such blocking a user, IP, or request.
Do not write any response to the client when you receive a BlockingSecurityEvent error. A response could potentially send sensitive information to an attacker. To safely detect this type of error, use the helper function events.IsSecurityError.
When a BlockingSecurityEvent is returned, the SDK automatically sends a blocking response for you, typically an HTTP 403 Forbidden.
By default, a lot of Go HTTP Frameworks are not high level enough to provide parsed HTTP request and response bodies. Consequently, the App and API Protection SDK provides a way to monitor the HTTP request and response bodies manually:
appsec.TrackUserLoginSuccess tracks a successful login event on your login endpoint. This function also calls appsec.SetUser internally to associate the user with the current request.
appsec.SetUser can be used on all authenticated requests to report users to Datadog and enable user blocking.
These functions automatically block the current request if the Protection feature is enabled, and return a BlockingSecurityEvent
error.
Custom event tracking
You can track Business logic events like user login success/failure using the appsec.TrackCustomEvent function. This function sets custom event data as service entry span tags, which triggers backend event monitoring, and can ultimately block IP addresses and/or associated user IDs.
Example
Here’s a concise example showing how to integrate the App and API Protection SDK into a standard net/http web application:
main.go
packagemainimport("encoding/json""log""net/http""strings""github.com/DataDog/dd-trace-go/v2/appsec""github.com/DataDog/dd-trace-go/v2/appsec/events""github.com/DataDog/dd-trace-go/v2/contrib/net/http/v2""github.com/DataDog/dd-trace-go/v2/ddtrace/tracer")typeLoginRequeststruct{Usernamestring`json:"username"`Passwordstring`json:"password"`}typeUserstruct{Namestring`json:name`Usernamestring`json:username`Emailstring`json:email`passwordstring}varusers=[]User{{Name:"John Doe",Username:"realjoe",Email:"john@gmail.com",password:"not-my-birthday",}}funcmain(){tracer.Start(tracer.WithService("my-web-app"),tracer.WithAppsecEnabled(true))defertracer.Stop()mux:=httptrace.NewServeMux()mux.HandleFunc("/login",loginHandler)mux.HandleFunc("/profile",authMiddleware(profileHandler))log.Fatal(http.ListenAndServe(":8080",mux))}funcloginHandler(whttp.ResponseWriter,r*http.Request){varreqLoginRequestjson.NewDecoder(r.Body).Decode(&req)// Monitor parsed request body
iferr:=appsec.MonitorParsedHTTPBody(r.Context(),req);err!=nil{ifevents.IsSecurityError(err){return// AppSec handles the blocking response
}}for_,user:=rangeusers{ifreq.Username==user.Username&&req.Password==user.Password{metadata:=map[string]string{"login_method":"password"}iferr:=appsec.TrackUserLoginSuccess(r.Context(),req.Username,"user123",metadata);err!=nil&&events.IsSecurityError(err){return// User is blocked
}response:=map[string]string{"token":"<token_created>","status":"success"}// Monitor response body
appsec.MonitorHTTPResponseBody(r.Context(),response)w.Header().Set("Content-Type","application/json")json.NewEncoder(w).Encode(response)return}}// Track failed login
appsec.TrackUserLoginFailure(r.Context(),req.Username,true,metadata)http.Error(w,"Invalid credentials",http.StatusUnauthorized)}funcauthMiddleware(nexthttp.HandlerFunc)http.HandlerFunc{returnfunc(whttp.ResponseWriter,r*http.Request){user:="<username>"// Do real authentification here
// Set user context on all authenticated requests
iferr:=appsec.SetUser(r.Context(),user);err!=nil&&events.IsSecurityError(err){return// User is blocked
}next.ServeHTTP(w,r)}}funcprofileHandler(whttp.ResponseWriter,r*http.Request){// Track access to sensitive data
appsec.TrackCustomEvent(r.Context(),"profile.access",map[string]string{"data_type":"personal_info",})userAsked:=r.Query().Get("user")user:=users[0]// Search for the user
// Monitor response body
appsec.MonitorHTTPResponseBody(r.Context(),user);w.Header().Set("Content-Type","application/json")json.NewEncoder(w).Encode(user)}
This example demonstrates:
Body Monitoring: MonitorParsedHTTPBody and MonitorHTTPResponseBody for request/response security
User Tracking: TrackUserLoginSuccess/TrackUserLoginFailure for login events, SetUser for authentication
Custom Events: TrackCustomEvent for business logic monitoring
Error Handling: Proper BlockingSecurityEvent handling with IsSecurityError
Key points:
Always check IsSecurityError(err) and return without writing responses when blocked
Use SetUser on authenticated requests to enable user blocking capabilities
Track important business events that could indicate suspicious activity
Further Reading
Additional helpful documentation, links, and articles: