package api import ( "net/http" "strings" ) const maxBody = 4 << 20 // folga sobre o limite de conteúdo da store (2 MiB) // maxRenderInput limita o tamanho do markdown aceito pelo endpoint de render: // conversão goldmark é O(n)–O(n²) por extensão; sem cap, 1 MiB perverso de // entrada produz ~2 MiB de HTML (amplificação medida) e consome CPU. const maxRenderInput = 512 << 10 // 512 KiB type renderInput struct { Content string `json:"content"` Format string `json:"format"` } // handleRender converte Markdown em HTML seguro (raw HTML do markdown é // escapado pelo goldmark; a nota em si é sempre renderizada via innerHTML). func (s *Server) handleRender(w http.ResponseWriter, r *http.Request) { var in renderInput if err := decodeJSON(w, r, &in, maxBody); err != nil { return } if len(in.Content) > maxRenderInput { writeError(w, http.StatusRequestEntityTooLarge, "conteúdo para render excede 512 KiB") return } switch in.Format { case "html": // O preview de HTML usa iframe com sandbox no cliente; não renderiza aqui. writeError(w, http.StatusBadRequest, "formato html usa preview em iframe") return } var buf strings.Builder if err := s.md.Convert([]byte(in.Content), &buf); err != nil { writeError(w, http.StatusInternalServerError, "falha ao renderizar markdown") return } writeJSON(w, http.StatusOK, map[string]string{"html": buf.String()}) }