<commit_before>// SPDX-License-Identifier: MIT

package mux

import (
	"errors"
	"net/http"
	"strconv"
	"strings"

	"github.com/issue9/sliceutil"

	"github.com/issue9/mux/v5/internal/tree"
)

// CORS 跨域请求设置项
//
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
type CORS struct {
	// AllowedOrigins 允许的外部域名列表
	//
	// 可以是 *，如果包含了 *，那么其它的设置将不再启作用。
	// 此字段将被用于与请求头的 Origin 字段作验证，以确定是否放行该请求。
	//
	// 如果此值为空，表示不启用跨域的相关设置。
	AllowedOrigins []string
	anyOrigins     bool
	deny           bool

	// AllowedHeaders 实际请求中允许携带的报头
	//
	// 可以包含 *，表示可以是任意值，其它值将不再启作用。
	AllowedHeaders       []string
	allowedHeadersString string
	anyHeaders           bool

	// ExposedHeaders Access-Control-Expose-Headers
	ExposedHeaders       []string
	exposedHeadersString string

	// MaxAge 当前报头信息可被缓存的秒数
	//
	// 0 不输出该 Access-Control-Max-Age 报头；
	// 其它 >= -1 的值正常输出数值；
	MaxAge       int
	maxAgeString string

	// AllowCredentials 是否允许 cookie
	AllowCredentials bool
}

// AllowedCORS 允许跨域请求
func AllowedCORS() *CORS {
	return &CORS{
		AllowedOrigins: []string{"*"},
		AllowedHeaders: []string{"*"},
		MaxAge:         3600,
	}
}

// DeniedCORS 禁用跨域请求
func DeniedCORS() *CORS { return &CORS{} }

func (c *CORS) sanitize() error {
	for _, o := range c.AllowedOrigins {
		if o == "*" {
			c.anyOrigins = true
			break
		}
	}
	c.deny = len(c.AllowedOrigins) == 0

	for _, h := range c.AllowedHeaders {
		if h == "*" {
			c.allowedHeadersString = "*"
			c.anyHeaders = true
			break<commit_msg>feat: 为 CORS 添加 struct tag<commit_after>// SPDX-License-Identifier: MIT

package mux

import (
	"errors"
	"net/http"
	"strconv"
	"strings"

	"github.com/issue9/sliceutil"

	"github.com/issue9/mux/v5/internal/tree"
)

// CORS 跨域请求设置项
//
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
type CORS struct {
	XMLName struct{} `json:"-" yaml:"-" xml:"cors"`

	// AllowedOrigins 对应 Origin
	//
	// 可以是 *，如果包含了 *，那么其它的设置将不再启作用。
	// 此字段将被用于与请求头的 Origin 字段作验证，以确定是否放行该请求。
	//
	// 如果此值为空，表示不启用跨域的相关设置。
	AllowedOrigins []string `json:"allowedOrigins,omitempty" yaml:"allowedOrigins,omitempty" xml:"allowedOrigins,omitempty"`
	anyOrigins     bool
	deny           bool

	// AllowedHeaders 对应 Access-Control-Allow-Headers
	//
	// 可以包含 *，表示可以是任意值，其它值将不再启作用。
	AllowedHeaders       []string `json:"allowedHeaders,omitempty" yaml:"allowedHeaders,omitempty" xml:"allowedHeaders,omitempty"`
	allowedHeadersString string
	anyHeaders           bool

	// ExposedHeaders 对应 Access-Control-Expose-Headers
	ExposedHeaders       []string `json:"exposedHeaders,omitempty" yaml:"exposedHeaders,omitempty" xml:"exposedHeaders,omitempty"`
	exposedHeadersString string

	// MaxAge 当前报头信息可被缓存的秒数
	//
	// 0 不输出该 Access-Control-Max-Age 报头；
	// 其它 >= -1 的值正常输出数值；
	MaxAge       int `json:"maxAge,omitempty" yaml:"maxAge,omitempty" xml:"maxAge,attr,omitempty"`
	maxAgeString string

	// AllowCredentials 是否允许 cookie
	AllowCredentials bool `json:"allowCredentials,omitempty" yaml:"allowCredentials,omitempty" xml:"allowCredentials,attr,omitempty"`
}

// AllowedCORS 允许跨域请求
func AllowedCORS() *CORS {
	return &CORS{
		AllowedOrigins: []string{"*"},
		AllowedHeaders: []string{"*"},
		MaxAge:         3600,
	}
}

// DeniedCORS 禁用跨域请求
func DeniedCORS() *CORS { return &CORS{} }

func (c *CORS) sanitize() error {
	for _, o := range c.AllowedOrigins {
		if o == "*" {
			c.anyOrigins = true
			break
		}
	}
	c.deny = len(c.AllowedOrigins) == 0

	for _, h := range c.AllowedHeaders {
		if h == "*" {
			c.allowedHeadersString = "*"
			c.anyHeaders = true
			break
{'fraction_non_alphanumeric': 0.13880938752146538, 'fraction_numerical': 0.005724098454493417, 'mean_word_length': 3.5038659793814433, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3443828', 'n_tokens_mistral': 1556, 'n_tokens_neox': 1573, 'n_words': 255}